diff --git a/.fixtures.yml b/.fixtures.yml index c2a5c35..5329d1c 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -2,5 +2,6 @@ fixtures: repositories: stdlib: "git://github.com/puppetlabs/puppetlabs-stdlib.git" concat: "git://github.com/puppetlabs/puppetlabs-concat.git" + host: "git://github.com/puppetlabs/puppetlabs-host_core.git" symlinks: network: "#{source_dir}" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9032a01 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +*.rb eol=lf +*.erb eol=lf +*.pp eol=lf +*.sh eol=lf +*.epp eol=lf diff --git a/.gitignore b/.gitignore index 4cc8399..2767022 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,27 @@ -.*.sw? -pkg -spec/fixtures -.rspec_system -*.un~ -Gemfile.lock -.bundle -vendor - +.git/ +.*.sw[op] +.metadata +.yardoc +.yardwarns +*.iml +/.bundle/ +/.idea/ +/.vagrant/ +/coverage/ +/bin/ +/doc/ +/Gemfile.local +/Gemfile.lock +/junit/ +/log/ +/pkg/ +/spec/fixtures/manifests/ +/spec/fixtures/modules/ +/tmp/ +/vendor/ +/convert_report.txt +/update_report.txt +.DS_Store +.project +.envrc +/inventory.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..81e6d76 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,41 @@ +--- +stages: + - syntax + - unit + +cache: + paths: + - vendor/bundle + +before_script: + - bundle -v + - rm Gemfile.lock || true + - gem update --system $RUBYGEMS_VERSION + - gem --version + - bundle -v + - bundle install --without system_tests --path vendor/bundle --jobs $(nproc) + +syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop-Ruby 2.5.3-Puppet ~> 6: + stage: syntax + image: ruby:2.5.3 + script: + - bundle exec rake syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop + variables: + PUPPET_GEM_VERSION: '~> 6' + +parallel_spec-Ruby 2.5.3-Puppet ~> 6: + stage: unit + image: ruby:2.5.3 + script: + - bundle exec rake parallel_spec + variables: + PUPPET_GEM_VERSION: '~> 6' + +parallel_spec-Ruby 2.4.5-Puppet ~> 5: + stage: unit + image: ruby:2.4.5 + script: + - bundle exec rake parallel_spec + variables: + PUPPET_GEM_VERSION: '~> 5' + diff --git a/.pdkignore b/.pdkignore new file mode 100644 index 0000000..e6215cd --- /dev/null +++ b/.pdkignore @@ -0,0 +1,42 @@ +.git/ +.*.sw[op] +.metadata +.yardoc +.yardwarns +*.iml +/.bundle/ +/.idea/ +/.vagrant/ +/coverage/ +/bin/ +/doc/ +/Gemfile.local +/Gemfile.lock +/junit/ +/log/ +/pkg/ +/spec/fixtures/manifests/ +/spec/fixtures/modules/ +/tmp/ +/vendor/ +/convert_report.txt +/update_report.txt +.DS_Store +.project +.envrc +/inventory.yaml +/appveyor.yml +/.fixtures.yml +/Gemfile +/.gitattributes +/.gitignore +/.gitlab-ci.yml +/.pdkignore +/Rakefile +/rakelib/ +/.rspec +/.rubocop.yml +/.travis.yml +/.yardopts +/spec/ +/.vscode/ diff --git a/.puppet-lint.rc b/.puppet-lint.rc new file mode 100644 index 0000000..cc96ece --- /dev/null +++ b/.puppet-lint.rc @@ -0,0 +1 @@ +--relative diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..16f9cdb --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--format documentation diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..f5a6c2a --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,122 @@ +--- +require: rubocop-rspec +AllCops: + DisplayCopNames: true + TargetRubyVersion: '2.1' + Include: + - "./**/*.rb" + Exclude: + - bin/* + - ".vendor/**/*" + - "**/Gemfile" + - "**/Rakefile" + - pkg/**/* + - spec/fixtures/**/* + - vendor/**/* + - "**/Puppetfile" + - "**/Vagrantfile" + - "**/Guardfile" +Metrics/LineLength: + Description: People have wide screens, use them. + Max: 200 +GetText/DecorateString: + Description: We don't want to decorate test output. + Exclude: + - spec/* +RSpec/BeforeAfterAll: + Description: Beware of using after(:all) as it may cause state to leak between tests. + A necessary evil in acceptance testing. + Exclude: + - spec/acceptance/**/*.rb +RSpec/HookArgument: + Description: Prefer explicit :each argument, matching existing module's style + EnforcedStyle: each +Style/BlockDelimiters: + Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to + be consistent then. + EnforcedStyle: braces_for_chaining +Style/ClassAndModuleChildren: + Description: Compact style reduces the required amount of indentation. + EnforcedStyle: compact +Style/EmptyElse: + Description: Enforce against empty else clauses, but allow `nil` for clarity. + EnforcedStyle: empty +Style/FormatString: + Description: Following the main puppet project's style, prefer the % format format. + EnforcedStyle: percent +Style/FormatStringToken: + Description: Following the main puppet project's style, prefer the simpler template + tokens over annotated ones. + EnforcedStyle: template +Style/Lambda: + Description: Prefer the keyword for easier discoverability. + EnforcedStyle: literal +Style/RegexpLiteral: + Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 + EnforcedStyle: percent_r +Style/TernaryParentheses: + Description: Checks for use of parentheses around ternary conditions. Enforce parentheses + on complex expressions for better readability, but seriously consider breaking + it up. + EnforcedStyle: require_parentheses_when_complex +Style/TrailingCommaInArguments: + Description: Prefer always trailing comma on multiline argument lists. This makes + diffs, and re-ordering nicer. + EnforcedStyleForMultiline: comma +Style/TrailingCommaInLiteral: + Description: Prefer always trailing comma on multiline literals. This makes diffs, + and re-ordering nicer. + EnforcedStyleForMultiline: comma +Style/SymbolArray: + Description: Using percent style obscures symbolic intent of array's contents. + EnforcedStyle: brackets +RSpec/MessageSpies: + EnforcedStyle: receive +Style/Documentation: + Exclude: + - lib/puppet/parser/functions/**/* + - spec/**/* +Style/WordArray: + EnforcedStyle: brackets +Style/CollectionMethods: + Enabled: true +Style/MethodCalledOnDoEndBlock: + Enabled: true +Style/StringMethods: + Enabled: true +Layout/EndOfLine: + Enabled: false +Layout/IndentHeredoc: + Enabled: false +Metrics/AbcSize: + Enabled: false +Metrics/BlockLength: + Enabled: false +Metrics/ClassLength: + Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/ModuleLength: + Enabled: false +Metrics/ParameterLists: + Enabled: false +Metrics/PerceivedComplexity: + Enabled: false +RSpec/DescribeClass: + Enabled: false +RSpec/ExampleLength: + Enabled: false +RSpec/MessageExpectation: + Enabled: false +RSpec/MultipleExpectations: + Enabled: false +RSpec/NestedGroups: + Enabled: false +Style/AsciiComments: + Enabled: false +Style/IfUnlessModifier: + Enabled: false +Style/SymbolProc: + Enabled: false diff --git a/.travis.yml b/.travis.yml index 46cc24b..23816f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,69 @@ --- -sudo: false +dist: trusty language: ruby cache: bundler -script: 'bundle exec rake validate lint spec' before_install: - - gem update bundler + - bundle -v + - rm -f Gemfile.lock + - gem update --system $RUBYGEMS_VERSION + - gem --version + - bundle -v +script: + - 'bundle exec rake $CHECK' +bundler_args: --without system_tests +rvm: + - 2.5.3 +stages: + - static + - spec + - acceptance + - + if: tag =~ ^v\d + name: deploy matrix: fast_finish: true include: - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 3.6.0" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 3" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 4" - - rvm: 2.4.1 - env: PUPPET_GEM_VERSION="~> 5" + - + rvm: 2.5.3 + env: CHECK="rubocop" + stage: static + - + rvm: 2.5.3 + env: CHECK="check:symlinks check:git_ignore check:dot_underscore check:test_file syntax lint metadata_lint" + stage: static + - + env: PUPPET_GEM_VERSION="~> 4.0" CHECK=parallel_spec + rvm: 2.4.5 + stage: spec + - + env: PUPPET_GEM_VERSION="~> 5.0" CHECK=parallel_spec + rvm: 2.4.5 + stage: spec + - + env: PUPPET_GEM_VERSION="~> 6.0" CHECK=parallel_spec + rvm: 2.5.3 + stage: spec + - + env: DEPLOY_TO_FORGE=yes + stage: deploy + + allow_failures: + - + rvm: 2.5.3 + env: CHECK="rubocop" + stage: static +branches: + only: + - master + - /^v\d/ notifications: - email: - - al@example42.com + email: false +deploy: + provider: puppetforge + user: example42 + password: + secure: "" + on: + tags: true + all_branches: true + condition: "$DEPLOY_TO_FORGE = yes" diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000..29c933b --- /dev/null +++ b/.yardopts @@ -0,0 +1 @@ +--markup markdown diff --git a/Gemfile b/Gemfile index 683560c..cf2c387 100644 --- a/Gemfile +++ b/Gemfile @@ -1,25 +1,15 @@ -# Based on pdk default Gemfile -# Added danger gems - source ENV['GEM_SOURCE'] || 'https://rubygems.org' def location_for(place_or_version, fake_version = nil) - if place_or_version =~ %r{\A(git[:@][^#]*)#(.*)} - [fake_version, { git: Regexp.last_match(1), branch: Regexp.last_match(2), require: false }].compact - elsif place_or_version =~ %r{\Afile:\/\/(.*)} - ['>= 0', { path: File.expand_path(Regexp.last_match(1)), require: false }] - else - [place_or_version, { require: false }] - end -end + git_url_regex = %r{\A(?(https?|git)[:@][^#]*)(#(?.*))?} + file_url_regex = %r{\Afile:\/\/(?.*)} -def gem_type(place_or_version) - if place_or_version =~ %r{\Agit[:@]} - :git - elsif !place_or_version.nil? && place_or_version.start_with?('file:') - :file + if place_or_version && (git_url = place_or_version.match(git_url_regex)) + [fake_version, { git: git_url[:url], branch: git_url[:branch], require: false }].compact + elsif place_or_version && (file_url = place_or_version.match(file_url_regex)) + ['>= 0', { path: File.expand_path(file_url[:path]), require: false }] else - :gem + [place_or_version, { require: false }] end end @@ -31,6 +21,8 @@ group :development do gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9') + gem "json", '= 2.0.4', require: false if Gem::Requirement.create('~> 2.4.2').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) gem "puppet-module-posix-default-r#{minor_version}", require: false, platforms: [:ruby] gem "puppet-module-posix-dev-r#{minor_version}", require: false, platforms: [:ruby] gem "puppet-module-win-default-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] @@ -38,86 +30,29 @@ group :development do end puppet_version = ENV['PUPPET_GEM_VERSION'] -puppet_type = gem_type(puppet_version) facter_version = ENV['FACTER_GEM_VERSION'] hiera_version = ENV['HIERA_GEM_VERSION'] -def puppet_older_than?(version) - puppet_version = ENV['PUPPET_GEM_VERSION'] - !puppet_version.nil? && - Gem::Version.correct?(puppet_version) && - Gem::Requirement.new("< #{version}").satisfied_by?(Gem::Version.new(puppet_version.dup)) -end - gems = {} gems['puppet'] = location_for(puppet_version) # If facter or hiera versions have been specified via the environment -# variables, use those versions. If not, and if the puppet version is < 3.5.0, -# use known good versions of both for puppet < 3.5.0. -if facter_version - gems['facter'] = location_for(facter_version) -elsif puppet_type == :gem && puppet_older_than?('3.5.0') - gems['facter'] = ['>= 1.6.11', '<= 1.7.5', require: false] -end - -if hiera_version - gems['hiera'] = location_for(ENV['HIERA_GEM_VERSION']) -elsif puppet_type == :gem && puppet_older_than?('3.5.0') - gem['hiera'] = ['>= 1.0.0', '<= 1.3.0', require: false] -end +# variables -if Gem.win_platform? && (puppet_type != :gem || puppet_older_than?('3.5.0')) - # For Puppet gems < 3.5.0 (tested as far back as 3.0.0) on Windows - if puppet_type == :gem - gems['ffi'] = ['1.9.0', require: false] - gems['minitar'] = ['0.5.4', require: false] - gems['win32-eventlog'] = ['0.5.3', '<= 0.6.5', require: false] - gems['win32-process'] = ['0.6.5', '<= 0.7.5', require: false] - gems['win32-security'] = ['~> 0.1.2', '<= 0.2.5', require: false] - gems['win32-service'] = ['0.7.2', '<= 0.8.8', require: false] - else - gems['ffi'] = ['~> 1.9.0', require: false] - gems['minitar'] = ['~> 0.5.4', require: false] - gems['win32-eventlog'] = ['~> 0.5', '<= 0.6.5', require: false] - gems['win32-process'] = ['~> 0.6', '<= 0.7.5', require: false] - gems['win32-security'] = ['~> 0.1', '<= 0.2.5', require: false] - gems['win32-service'] = ['~> 0.7', '<= 0.8.8', require: false] - end - - gems['win32-dir'] = ['~> 0.3', '<= 0.4.9', require: false] +gems['facter'] = location_for(facter_version) if facter_version +gems['hiera'] = location_for(hiera_version) if hiera_version - if RUBY_VERSION.start_with?('1.') - gems['win32console'] = ['1.3.2', require: false] - # sys-admin was removed in Puppet 3.7.0 and doesn't compile under Ruby 2.x - gems['sys-admin'] = ['1.5.6', require: false] - end - - # Puppet < 3.7.0 requires these. - # Puppet >= 3.5.0 gem includes these as requirements. - # The following versions are tested to work with 3.0.0 <= puppet < 3.7.0. - gems['win32-api'] = ['1.4.8', require: false] - gems['win32-taskscheduler'] = ['0.2.2', require: false] - gems['windows-api'] = ['0.4.3', require: false] - gems['windows-pr'] = ['1.2.3', require: false] -elsif Gem.win_platform? +if Gem.win_platform? && puppet_version =~ %r{^(file:///|git://)} # If we're using a Puppet gem on Windows which handles its own win32-xxx gem # dependencies (>= 3.5.0), set the maximum versions (see PUP-6445). gems['win32-dir'] = ['<= 0.4.9', require: false] gems['win32-eventlog'] = ['<= 0.6.5', require: false] gems['win32-process'] = ['<= 0.7.5', require: false] gems['win32-security'] = ['<= 0.2.5', require: false] - gems['win32-service'] = ['<= 0.8.8', require: false] + gems['win32-service'] = ['0.8.8', require: false] end -if puppet_older_than?('5.0.0') - # Hiera-eyaml is embedded in Hiera 5 / Puppet 5 -else - gems['hiera-eyaml'] = ['~> 2.0'] -end - - gems.each do |gem_name, gem_params| gem gem_name, *gem_params end @@ -133,16 +68,4 @@ extra_gemfiles.each do |gemfile| eval(File.read(gemfile), binding) end end - -# Danger integration: http://danger.systems -gem 'danger' -gem 'danger-changelog' -gem 'danger-mention' - -# Coveralls -gem 'coveralls', require: false - -# Semantic Puppet -gem 'semantic_puppet', require: false -gem 'puppet-blacksmith', require: false # vim: syntax=ruby diff --git a/README.md b/README.md index bb4f055..1b13e88 100644 --- a/README.md +++ b/README.md @@ -1,488 +1,164 @@ -# network -[![Build Status](https://travis-ci.org/example42/puppet-network.png?branch=master)](https://travis-ci.org/example42/puppet-network) +# example42 puppet-network module + +Example 42 Puppet module to manage networking on Linux and Solaris. #### Table of Contents -1. [Overview](#overview) -2. [Module Description](#module-description) -3. [Setup](#setup) - * [Resources managed by network module](#resources-managed-by-network-module) +1. [Description](#description) +2. [Setup - The basics of getting started with network](#setup) + * [What network affects](#what-network-affects) * [Setup requirements](#setup-requirements) - * [Beginning with module network](#beginning-with-module-network) -4. [Usage](#usage) -5. [Hiera examples](#hiera-examples) -6. [Operating Systems Support](#operating-systems-support) -7. [Development](#development) - -## Overview - -This module configures networking on Linux and Solaris. It manages network parameters, interfaces, routes, -rules and routing tables. - -## Module Description - -Main class is used as entrypoint for general variables. - -It manages hostname configuration and has hiera hash lookups to generate the following, provided, resources: - -- network::interface - Define to manage network interfaces -- network::route - Define to manage network routes -- network::mroute - Define to manage network routes - Alternative with easier management of multiple routes per interface -- network::routing_table - Define to manage iproute2 routing tables -- network::rule - Define to manage network rules - -## Setup - -### Setup Requirements -* PuppetLabs [stdlib module](https://github.com/puppetlabs/puppetlabs-stdlib) -* PuppetLabs [concat module](https://github.com/puppetlabs/puppetlabs-concat) -* Puppet version >= 3.0.0 < 7.0.0 -* Facter version >= 1.6.2 - -### Beginning with module network - -The main class arguments can be provided either via Hiera (from Puppet 3.x) or direct parameters: - - class { 'network': - parameter => value, - } - - -The module provides a generic network::conf define to manage any file in the config_dir_path which is: - - On 'Debian' osfamily: '/etc/network', - - On 'Redhat' osfamily: '/etc/sysconfig/network-scripts', - - On 'Suse' osfamily: '/etc/sysconfig/network', - - network::conf { 'if-up.d/my_script': - template => 'site/network/my_script', - } - -The module provides a cross OS compliant define to manage single interfaces: network::interface - -IMPORTANT NOTICE: On Debian if you use network::interface once you must provide ALL the network::interface defines for all your interfaces. It requires separate declarations for each IP stack on each interface. -Please keep in mind Debian and RedHat do not share the same approach in IPv4 / IPv6 management and thus require different hash structures. - -To configure a dhcp interface - - network::interface { 'eth0': - enable_dhcp => true, - } - -To configure a static interface with basic parameters - - network::interface { 'eth1': - ipaddress => '10.42.42.50', - netmask => '255.255.255.0', - } - - -## Generic interface parameters configation examples - -You have different possible approaches in the usage of this module. Use the one you prefer. - -* Just use the network::interface defines: - - network::interface { 'eth0': - enable_dhcp => true, - } - - network::interface { 'eth1': - ipaddress => '10.42.42.50', - netmask => '255.255.255.0', - } - -* Use the main network class and the interfaces_hash to configure all the interfaces - - class { 'network': - interfaces_hash => { - 'eth0' => { - enable_dhcp => true, - }, - 'eth1' => { - ipaddress => '10.42.42.50', - netmask => '255.255.255.0', - }, - }, - } - -Same information as Hiera data in yaml format: - - network::interfaces_hash: - eth0: - enable_dhcp: true - eth1: - ipaddress: '10.42.42.50' - netmask: '255.255.255.0' - -* Use the main network class and the usual stdmod parameters to manage the (main) network configuration file - - On 'Debian' osfamily: '/etc/network/interfaces', + * [Beginning with network](#beginning-with-network) +3. [Usage - Configuration options and additional functionality](#usage) +4. [Reference - An under-the-hood peek at what the module is doing and how](#reference) +5. [Backwards compatibility](#backwards-compatibility) +6. [## Upgrade from version 3 and migration](#upgrade-from-version-3-and-migration) +6. [Limitations - OS compatibility, etc.](#limitations) +7. [Development - Guide for contributing to the module](#development) - On 'Redhat' osfamily: '/etc/sysconfig/network-scripts/ifcfg-eth0' # Yes, quite opinionated, you can change it with config_file_path. +## Description - On 'Suse' osfamily: '/etc/sysconfig/network/ifcfg-eth0' +This module configures networking on Linux and Solaris. - class { 'network': - config_file_template => 'site/network/network.conf.erb', - } +It manages hostname, interfaces, routes, rules and routing tables. -* Manage the whole configuration directory +The new version (4) works only on Puppet 4 and later and has several changes in class and defines parameters. - class { 'network': - config_dir_source => 'puppet:///modules/site/network/conf/', - } +Options to provide [backwards compatibility](#backwards-compatibility) are available in order to use the legacy versions of the module's defines. -* DO NOT automatically restart the network service after configuration changes (either via the main network class or via network::interfaces) +## Module Description - class { 'network': - config_file_notify => '', - } +Main class is used as entrypoint for general variables and wrapper for Hiera driven management of the provided defines. +Classes: -* The network::interface exposes, and uses in the default templates, network configuration parameters available on Debian (most), RedHat (some), Suse (most) so it's flexible, easily expandable and should adapt to any need, but you may still want to provide a custom template with: +- network - Allows Hiera driven configuration of the various defines +- network::hostname - Manages the system hostname - network::interface { 'eth0': - enable_dhcp => true, - template => "site/network/interface/${::osfamily}.erb", - } +Defines: -## Network routes management examples +- network::interface - Manages network interfaces +- network::route - Manages network routes +- network::routing_table - Manages iproute2 routing tables +- network::rule - Manages network rules +- network::netplan - Generic netplan.io configuration +- network::netplan::interface - Netplan.io interface configuration -* The network::route can be used to define static routes on Debian and RedHat systems. The following example manages a static route on eth0 +Legacy defines (inherited from version 3 of the module): - network::route { 'eth0': - ipaddress => [ '192.168.17.0', ], - netmask => [ '255.255.255.0', ], - gateway => [ '192.168.17.250', ], - } +- network::legacy::interface - Manages network interfaces +- network::legacy::route - Manages network routes +- network::legacy::mroute - Manages network routes in an alternative, easier to handle, way +- network::legacy::routing_table - Manages iproute2 routing tables +- network::legacy::rule - Manages network rules - On 'Debian' osfamily: it will create 2 files: '/etc/network/if-up.d/z90-route-eth0' and '/etc/network/if-down.d/z90-route-eth0', +## Setup - On 'RedHat' osfamily: it will create the file '/etc/sysconfig/network-scripts/route-eth0' - You can provide to the main network class the routes_hash parameter to manage all your routes via a hash. +### What puppet-network affects -* This example add 2 static routes on the interface bond2 +The main network class does nothing with default values for parameters but can be included and used +as entrypoints to manage via Hiera hashes of the defines provided in the modules. - network::route { 'bond2': - ipaddress => [ '192.168.2.0', '10.0.0.0', ], - netmask => [ '255.255.255.0', '255.0.0.0', ], - gateway => [ '192.168.1.1', '10.0.0.1', ], - } +Single defines manage the relevant network entity (interfaces, routes, rules, tables ...) -* To configure the default route on Suse, use the routes_hash parameter, like in the following example: +### Setup Requirements - class { 'network': - routes_hash => { - 'eth0' => { - ipaddress => [ 'default', ], - gateway => [ '192.168.0.1', ], - netmask => [ '-', ], - interface => 'eth0', - } - } - } +Puppetlabs-stdlib module is the only prerequisite module. -* An alternative way to manage routes is using the network::mroute define, which expects a hash of one or more routes where you specify the network and the gateway (either as ip or device name): +Puppet 4 or later is required for this module. - network::mroute { 'bond2': - routes => { - '192.168.2.0/24' => '192.168.1.1', - '10.0.0.0/8' => '10.0.0.1', - '80.81.82.0/16' => 'bond0', - } - } +If you have earlier Puppet versions use code from the 3.x tags. -* The network::routing_table and network::rule classes can be used to configure ip rules and routing tables. Make sure to define a routing table before using it, like in this example: +### Beginning with network - network::routing_table { 'vlan22': - table_id => '200', - } +Include the main class to be able to manage via Hiera the network resources handled by the module: - network::rule { 'eth0': - iprule => ['from 192.168.22.0/24 lookup vlan22', ], - } + include network + +This allows to configure network resources with Hiera data like: -You can then add routes to this routing table: + network::hostname: server.example.com + network::interfaces_hash: + eth0: + enable_dhcp: true + eth1: + ipaddress: '10.42.42.50' + netmask: '255.255.255.0' + network::routes_hash: + eth1: + routes: + 99.99.228.0/24: eth0 + 100.100.244.0/22: 174.136.107.1 + 101.99.228.0/24: 'eth0 table 1' + +## Usage - network::route { 'eth1': - ipaddress => [ '192.168.22.0', ], - netmask => [ '255.255.255.0', ], - gateway => [ '192.168.22.1', ], - table => [ 'vlan22' ], - } -If adding routes to a routing table on an interface with multiple routes, it -is necessary to specify false or 'main' for the table on the other routes. -The 'main' routing table is where routes are added by default. E.g. this: +## Reference - network::route { 'bond0': - ipaddress => [ '192.168.2.0', '10.0.0.0', ] - netmask => [ '255.255.255.0', '255.0.0.0', ], - gateway => [ '192.168.1.1', '10.0.0.1', ], - } +For full reference look at the defines documentation. - network::route { 'bond0': - ipaddress => [ '192.168.3.0', ], - netmask => [ '255.255.255.0', ], - gateway => [ '192.168.3.1', ], - table => [ 'vlan22' ], - } +For configuration examples via Hiera look at the examples directory. -would need to become: +## Upgrade from version 3 and migration - network::route { 'bond0': - ipaddress => [ '192.168.2.0', '10.0.0.0', '192.168.3.0', ] - netmask => [ '255.255.255.0', '255.0.0.0', '255.255.255.0', ], - gateway => [ '192.168.1.1', '10.0.0.1', '192.168.3.1', ], - table => [ false, false, 'vlan22' ], - } +When upgrading from version 3 to version 4 of this module you have 2 options: -The same applies if adding scope, source or gateway, i.e. false needs to be -specified for those routes without values for those parameters, if defining -multiple routes for the same interface. +- Keep on using the old defines with relevant data +- Migrate to the new defines -The following definition: +### Keep on using old defines - network::route { 'bond2': - ipaddress => [ '0.0.0.0', '192.168.3.0' ] - netmask => [ '0.0.0.0', '255.255.255.0' ], - gateway => [ '192.168.3.1', false ], - scope => [ false, 'link', ], - source => [ false, '192.168.3.10', ], - table => [ 'vlan22' 'vlan22', ], - } +The Version 3 defines for network resources have been renamed to legacy but they entrypoint have been preserved, so, if you managed your network cnfigurations via the network::*_hash Hiera keys you should not have any change in behaviour. -yields the following routes in table vlan22: +| Version 3 defines | Version 4 equivalent | Hiera entrypoint | +| network::interface | network::legacy::interface | network::interfaces_hash | +| network::route | network::legacy::route | network::routes_hash | +| network::mroute | network::legacy::mroute | network::mroutes_hash | +| network::rule | network::legacy::rule | network::rules_hash | +| network::routing_table | network::legacy::routing_table | network::tables_hash | - # ip route show table vlan22 - default via 192.168.3.1 dev bond2 - 192.168.3.0/255.255.255.0 dev bond2 scope link src 192.168.3.10 +If you use in you profile, classes or wrapper defines directly the above version 3 defines, then you need to rename them using the legacy names. -Normally the link level routing (192.168.3.0/255.255.255.0) is added -automatically by the kernel when an interface is brought up. When using routing -rules and routing tables, this does not happen, so this route must be added -manually. +Given the quite critical nature of the resources managed we highly recommend to test carefully the effect of an upgrade of +this module on your current infrastructure and to keep the first runs on noop mode. +Some configuration files might change as well, in minor details like new lines or spaces, even when using the legacy defines. To avoid automatic restart of network service on a configuration change set: -## Hiera examples + network::config_file_notify: false -Here are some examples of usage via Hiera (with yaml backend). +### Miggrate to the new defines -Main class settings: +The new, version 4 defines have replaced the names of the old ones and can be configured via hiera using new entrypoints in the netwrok class: - network::hostname: 'web01' - network::gateway: 192.168.0.1 # Default gateway (on RHEL systems) - network::hiera_merge: true # Use hiera_hash() instead of hiera() to resolve the values for the following hashes +| Version 4 defines | Hiera entrypoint | +| network::interface | network::interfaces | +| network::route | network::routes | +| network::mroute | network::mroutes | +| network::rule | network::rules | +| network::routing_table | network::tables | -Configuration of interfaces (check ```network::interface``` for all the available params. +The parameters of these defines have changes and, in many cases, also their internals. -Single interface via dhcp: +## Limitations - network::interfaces_hash: - eth0: - enable_dhcp: true - -Bond interface: - - eth0: - method: manual - bond_master: 'bond3' - allow_hotplug: 'eth0' - manage_order: '08' - eth1: - method: manual - bond_master: 'bond3' - allow_hotplug: 'eth1' - manage_order: '08' - bond3: - ipaddress: "10.0.28.10" - netmask: '255.255.248.0' - gateway: "10.0.24.1" - dns_nameservers: "8.8.8.8 8.8.4.4" - dns_search: 'my.domain' - bond_mode: 'balance-alb' - bond_miimon: '100' - bond_slaves: [] - -Debian/Ubuntu IPv4/IPv6 management example for basic IP config, IP aliaseconfig and VLAN config : - - 'eth0:0v4': - 'enable': 'true' - 'bootproto': 'none' - 'peerdns': 'no' - 'userctl': 'no' - 'restart_all_nic': 'false' - 'accept_ra': '1' - 'type': 'Ethernet' - 'mtu': '1500' - 'interface': 'eth0:0' - 'ipaddress': 'X.X.X.X/22' - 'family': 'inet' - - 'eth0:0v6': - 'enable': 'true' - 'bootproto': 'none' - 'peerdns': 'no' - 'userctl': 'no' - 'restart_all_nic': 'false' - 'accept_ra': '1' - 'autoconf': '0' - 'type': 'Ethernet' - 'mtu': '1500' - 'interface': 'eth0:0' - 'ipaddress': 'X.X.X.1::85/64' - 'family': 'inet6' - - 'eth1v4': - 'enable': 'true' - 'bootproto': 'none' - 'peerdns': 'no' - 'userctl': 'no' - 'restart_all_nic': 'false' - 'accept_ra': '0' - 'type': 'Ethernet' - 'mtu': '1500' - 'interface': 'eth1' - 'ipaddress': 'X.X.X.1/29' - 'family': 'inet' - - 'eth1v6': - 'enable': 'true' - 'bootproto': 'none' - 'peerdns': 'no' - 'userctl': 'no' - 'restart_all_nic': 'false' - 'accept_ra': '0' - 'type': 'Ethernet' - 'mtu': '1500' - 'interface': 'eth1' - 'ipaddress': 'X.X.X.1:bb:43::2/64' - 'family': 'inet6' - - 'eth1.12v4': - 'enable': 'true' - 'bootproto': 'none' - 'peerdns': 'no' - 'userctl': 'no' - 'restart_all_nic': 'false' - 'accept_ra': '1' - 'type': 'Ethernet' - 'mtu': '1500' - 'vlan': 'yes' - 'interface': 'eth1.12' - 'ipaddress': 'X.X.X.1/29' - 'family': 'inet' - - 'eth1.12v6': - 'enable': 'true' - 'bootproto': 'none' - 'peerdns': 'no' - 'userctl': 'no' - 'restart_all_nic': 'false' - 'accept_ra': '1' - 'autoconf': '0' - 'type': 'Ethernet' - 'mtu': '1500' - 'vlan': 'yes' - 'interface': 'eth1.12' - 'ipaddress': 'X.X.X.1:dd:3::2/64' - 'family': 'inet6' - - 'eth0v4': - 'enable': 'true' - 'bootproto': 'none' - 'peerdns': 'no' - 'userctl': 'no' - 'restart_all_nic': 'false' - 'accept_ra': '1' - 'type': 'Ethernet' - 'mtu': '1500' - 'dns_nameservers': 'X.X.X.1 X.X.X.1 X.X.X.1' - 'interface': 'eth0' - 'ipaddress': 'X.X.X.X/22' - 'gateway': 'X.X.X.1' - 'family': 'inet' - - 'eth0v6': - 'enable': 'true' - 'bootproto': 'none' - 'peerdns': 'no' - 'userctl': 'no' - 'restart_all_nic': 'false' - 'accept_ra': '1' - 'autoconf': '0' - 'type': 'Ethernet' - 'mtu': '1500' - 'interface': 'eth0' - 'ipaddress': 'X.X.X.1::85/64' - 'gateway': 'X.X.X.1::1' - 'family': 'inet6' - -Configuration of multiple static routes (using the ```network::route``` define, when more than one route is added the elements of the arrays have to be ordered coherently): - - network::routes_hash: - eth0: - ipaddress: - - 99.99.228.0 - - 100.100.244.0 - netmask: - - 255.255.255.0 - - 255.255.252.0 - gateway: - - 192.168.0.1 - - 174.136.107.1 - - -Configuration of multiple static routes (using the newer ```network::mroute``` define) you can specify as gateway either a device or an IP or also add a table reference: - - network::mroutes_hash: - eth0: - routes: - 99.99.228.0/24: eth0 - 100.100.244.0/22: 174.136.107.1 - 101.99.228.0/24: 'eth0 table 1' +This module currently supports only the major Linux distributions (RedHat and derivatives, Debian and derivatives, included Cumulus, SuSE +and derivatives, Solaris). +The legacy defines are introduced for backwards compatibility only and are not supposed to be improved in the future. +The new, default, defines, are designed in a way to be more easily adaptable to custom needs (for example there's no need to add parameters +for any new or uncommon configuration entry). -## Operating Systems Support - -This is tested on these OS: - -- RedHat - - 5 - - 6 - - 7 -- Debian - - 6 - - 7 - - 8 -- Ubuntu - - 10.04 - - 12.04 - - 14.04 - - partly verified on Ubuntu 16.04 -- Suse (ifrule files are only supported on Suse with wicked >= 0.6.33) - - OpenSuse 12 - - SLES 11SP3 - - SLES 12SP1 - - SLES 15 +## Development +To contribute to the module submit a Pull Request on GitHub. -## Development +Please be sure to provide: -Pull requests (PR) and bug reports via GitHub are welcomed. +- Code changes for syntax and lint +- Relevant documentation +- Relevant spec tests -When submitting PR please follow these quidelines: -- Provide puppet-lint compliant code -- If possible provide rspec tests -- Follow the module style and stdmod naming standards -When submitting bug report please include or link: -- The Puppet code that triggers the error -- The output of facter on the system where you try it -- All the relevant error logs -- Any other information useful to understand the context diff --git a/Rakefile b/Rakefile index de1c314..750ef46 100644 --- a/Rakefile +++ b/Rakefile @@ -1,9 +1,76 @@ require 'puppetlabs_spec_helper/rake_tasks' require 'puppet-syntax/tasks/puppet-syntax' +require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any? +require 'github_changelog_generator/task' if Bundler.rubygems.find_name('github_changelog_generator').any? +require 'puppet-strings/tasks' if Bundler.rubygems.find_name('puppet-strings').any? -# Blacksmith -begin - require 'puppet_blacksmith/rake_tasks' -rescue LoadError - puts "Blacksmith needed only to push to the Forge" +def changelog_user + return unless Rake.application.top_level_tasks.include? "changelog" + returnVal = nil || JSON.load(File.read('metadata.json'))['author'] + raise "unable to find the changelog_user in .sync.yml, or the author in metadata.json" if returnVal.nil? + puts "GitHubChangelogGenerator user:#{returnVal}" + returnVal end + +def changelog_project + return unless Rake.application.top_level_tasks.include? "changelog" + returnVal = nil || JSON.load(File.read('metadata.json'))['name'] + raise "unable to find the changelog_project in .sync.yml or the name in metadata.json" if returnVal.nil? + puts "GitHubChangelogGenerator project:#{returnVal}" + returnVal +end + +def changelog_future_release + return unless Rake.application.top_level_tasks.include? "changelog" + returnVal = "v%s" % JSON.load(File.read('metadata.json'))['version'] + raise "unable to find the future_release (version) in metadata.json" if returnVal.nil? + puts "GitHubChangelogGenerator future_release:#{returnVal}" + returnVal +end + +PuppetLint.configuration.send('disable_relative') + +if Bundler.rubygems.find_name('github_changelog_generator').any? + GitHubChangelogGenerator::RakeTask.new :changelog do |config| + raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil? + config.user = "#{changelog_user}" + config.project = "#{changelog_project}" + config.future_release = "#{changelog_future_release}" + config.exclude_labels = ['maintenance'] + config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)." + config.add_pr_wo_labels = true + config.issues = false + config.merge_prefix = "### UNCATEGORIZED PRS; GO LABEL THEM" + config.configure_sections = { + "Changed" => { + "prefix" => "### Changed", + "labels" => ["backwards-incompatible"], + }, + "Added" => { + "prefix" => "### Added", + "labels" => ["feature", "enhancement"], + }, + "Fixed" => { + "prefix" => "### Fixed", + "labels" => ["bugfix"], + }, + } + end +else + desc 'Generate a Changelog from GitHub' + task :changelog do + raise <= Gem::Version.new('2.2.2')" +EOM + end +end + diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..e10ba3b --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,55 @@ +--- +version: 1.1.x.{build} +branches: + only: + - master +skip_commits: + message: /^\(?doc\)?.*/ +clone_depth: 10 +init: + - SET + - 'mkdir C:\ProgramData\PuppetLabs\code && exit 0' + - 'mkdir C:\ProgramData\PuppetLabs\facter && exit 0' + - 'mkdir C:\ProgramData\PuppetLabs\hiera && exit 0' + - 'mkdir C:\ProgramData\PuppetLabs\puppet\var && exit 0' +environment: + matrix: + - + RUBY_VERSION: 24-x64 + CHECK: syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop + - + PUPPET_GEM_VERSION: ~> 5.0 + RUBY_VERSION: 24 + CHECK: parallel_spec + - + PUPPET_GEM_VERSION: ~> 5.0 + RUBY_VERSION: 24-x64 + CHECK: parallel_spec + - + PUPPET_GEM_VERSION: ~> 6.0 + RUBY_VERSION: 25 + CHECK: parallel_spec + - + PUPPET_GEM_VERSION: ~> 6.0 + RUBY_VERSION: 25-x64 + CHECK: parallel_spec +matrix: + fast_finish: true +install: + - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% + - bundle install --jobs 4 --retry 2 --without system_tests + - type Gemfile.lock +build: off +test_script: + - bundle exec puppet -V + - ruby -v + - gem -v + - bundle -v + - bundle exec rake %CHECK% +notifications: + - provider: Email + to: + - nobody@nowhere.com + on_build_success: false + on_build_failure: false + on_build_status_changed: false diff --git a/data/Debian9.yaml b/data/Debian9.yaml new file mode 100644 index 0000000..35de2d0 --- /dev/null +++ b/data/Debian9.yaml @@ -0,0 +1,2 @@ +--- +network::service_restart_exec: 'systemctl restart network' diff --git a/data/Ubuntu14.04.yaml b/data/Ubuntu14.04.yaml new file mode 100644 index 0000000..29ecd42 --- /dev/null +++ b/data/Ubuntu14.04.yaml @@ -0,0 +1,2 @@ +--- +network::service_restart_exec: 'service networking reload' diff --git a/data/Ubuntu14.10.yaml b/data/Ubuntu14.10.yaml new file mode 100644 index 0000000..29ecd42 --- /dev/null +++ b/data/Ubuntu14.10.yaml @@ -0,0 +1,2 @@ +--- +network::service_restart_exec: 'service networking reload' diff --git a/data/Ubuntu16.04.yaml b/data/Ubuntu16.04.yaml new file mode 100644 index 0000000..b2b21c0 --- /dev/null +++ b/data/Ubuntu16.04.yaml @@ -0,0 +1,2 @@ +--- +network::service_restart_exec: 'systemctl restart networking' diff --git a/data/Ubuntu16.10.yaml b/data/Ubuntu16.10.yaml new file mode 100644 index 0000000..b2b21c0 --- /dev/null +++ b/data/Ubuntu16.10.yaml @@ -0,0 +1,2 @@ +--- +network::service_restart_exec: 'systemctl restart networking' diff --git a/data/Ubuntu17.04.yaml b/data/Ubuntu17.04.yaml new file mode 100644 index 0000000..b2b21c0 --- /dev/null +++ b/data/Ubuntu17.04.yaml @@ -0,0 +1,2 @@ +--- +network::service_restart_exec: 'systemctl restart networking' diff --git a/data/Ubuntu17.10.yaml b/data/Ubuntu17.10.yaml new file mode 100644 index 0000000..b2b21c0 --- /dev/null +++ b/data/Ubuntu17.10.yaml @@ -0,0 +1,2 @@ +--- +network::service_restart_exec: 'systemctl restart networking' diff --git a/data/Ubuntu18.04.yaml b/data/Ubuntu18.04.yaml new file mode 100644 index 0000000..b67b83b --- /dev/null +++ b/data/Ubuntu18.04.yaml @@ -0,0 +1,3 @@ +--- +network::use_netplan: true +network::service_restart_exec: 'netplan apply' diff --git a/data/osfamily/.gitkeep b/data/osfamily/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tests/init.pp b/examples/init.pp similarity index 100% rename from tests/init.pp rename to examples/init.pp diff --git a/examples/legacy.yaml b/examples/legacy.yaml new file mode 100644 index 0000000..bcfcbf5 --- /dev/null +++ b/examples/legacy.yaml @@ -0,0 +1,15 @@ +### +# Sample configurations using legacy defines +--- +network::routes_hash: + eth1: + routes: + '10.42.50.0/24': '10.42.43.1' + '10.42.100.0/24': '10.42.43.1' + '10.42.251.0/24': '10.42.43.1' +network::interfaces_hash: + 'eth0': + enable_dhcp: true + 'eth1': + ipaddress: '10.42.43.104' + netmask: '255.255.255.0' diff --git a/files/rt_tables b/files/legacy/rt_tables similarity index 100% rename from files/rt_tables rename to files/legacy/rt_tables diff --git a/hiera.yaml b/hiera.yaml new file mode 100644 index 0000000..f1c3c46 --- /dev/null +++ b/hiera.yaml @@ -0,0 +1,16 @@ +--- +version: 5 + +defaults: + datadir: data + data_hash: yaml_data + +hierarchy: + - name: "In module hierarchy" + paths: + - "%{facts.os.name}%{facts.os.release.major}.yaml" + - "%{facts.os.name}.yaml" + - "%{facts.os.family}%{facts.os.release.major}.yaml" + - "%{facts.os.family}.yaml" + - "%{facts.kernel}.yaml" + - "common.yaml" diff --git a/lib/puppet/functions/netmask2cidr.rb b/lib/puppet/functions/netmask2cidr.rb new file mode 100644 index 0000000..43afed0 --- /dev/null +++ b/lib/puppet/functions/netmask2cidr.rb @@ -0,0 +1,9 @@ +require 'ipaddr' +Puppet::Functions.create_function(:netmask2cidr, Puppet::Functions::InternalFunction) do + dispatch :single do + param 'Stdlib::IP::Address', :netmask + end + def single(netmask) + result = IPAddr.new(netmask).to_i.to_s(2).count("1") + end +end diff --git a/manifests/conf.pp b/manifests/conf.pp deleted file mode 100644 index 482d3fb..0000000 --- a/manifests/conf.pp +++ /dev/null @@ -1,115 +0,0 @@ -# -# = Define: network::conf -# -# With this define you can manage any network configuration file -# -# == Parameters -# -# [*template*] -# String. Optional. Default: undef. Alternative to: source, content. -# Sets the module path of a custom template to use as content of -# the config file -# When defined, config file has: content => content($template), -# Example: template => 'site/network/my.conf.erb', -# -# [*content*] -# String. Optional. Default: undef. Alternative to: template, source. -# Sets directly the value of the file's content parameter -# When defined, config file has: content => $content, -# Example: content => "# File manage by Puppet \n", -# -# [*source*] -# String. Optional. Default: undef. Alternative to: template, content. -# Sets the value of the file's source parameter -# When defined, config file has: source => $source, -# Example: source => 'puppet:///site/network/my.conf', -# -# [*ensure*] -# String. Default: present -# Manages config file presence. Possible values: -# * 'present' - Create and manages the file. -# * 'absent' - Remove the file. -# -# [*path*] -# String. Optional. Default: $config_dir/$title -# The path of the created config file. If not defined a file -# name like the the name of the title a custom template to -# use as content of configfile -# If defined, configfile file has: content => content("$template") -# -# [*mode*] -# [*owner*] -# [*group*] -# [*config_file_require*] -# [*replace*] -# String. Optional. Default: undef -# All these parameters map directly to the created file attributes. -# If not defined the module's defaults are used. -# If defined, config file file has, for example: mode => $mode -# -# [*config_file_notify*] -# String. Optional. Default: 'class_default' -# Defines the notify argument of the created file. -# The default special value implies the same behaviour of the main class -# configuration file. Set to undef to remove any notify, or set -# the name(s) of the resources to notify -# -# [*options_hash*] -# Hash. Default undef. Needs: 'template'. -# An hash of custom options to be used in templates to manage any key pairs of -# arbitrary settings. -# -define network::conf ( - - $source = undef, - $template = undef, - $content = undef, - - $path = undef, - $mode = undef, - $owner = undef, - $group = undef, - - $config_file_notify = 'class_default', - $config_file_require = undef, - - $options_hash = undef, - - $ensure = present ) { - - validate_re($ensure, ['present','absent'], 'Valid values are: present, absent. WARNING: If set to absent the conf file is removed.') - - include ::network - - $manage_path = pick($path, "${::network::config_dir_path}/${name}") - $manage_mode = pick($mode, $::network::config_file_mode) - $manage_owner = pick($owner, $::network::config_file_owner) - $manage_group = pick($group, $::network::config_file_group) - $manage_require = pick($config_file_require, $::network::config_file_require) - $manage_notify = $config_file_notify ? { - 'class_default' => $::network::manage_config_file_notify, - default => $config_file_notify, - } - $manage_content = $content ? { - undef => $template ? { - undef => undef, - default => template($template), - }, - default => $content, - } - - - file { "network_conf_${name}": - ensure => $ensure, - source => $source, - content => $manage_content, - path => $manage_path, - mode => $manage_mode, - owner => $manage_owner, - group => $manage_group, - require => $manage_require, - notify => $manage_notify, - } - -} - diff --git a/manifests/hostname.pp b/manifests/hostname.pp new file mode 100644 index 0000000..ae19062 --- /dev/null +++ b/manifests/hostname.pp @@ -0,0 +1,80 @@ +# A description of what this class does +# +# @summary A short summary of the purpose of this class +# +# @example +# include network::hostname +class network::hostname ( + Optional[String] $hostname_file_template = undef, + Boolean $hostname_legacy = false, + Hash $options = {}, +) { + + $hostname_default_template = $hostname_legacy ? { + true => "network/legacy/hostname-${::osfamily}.erb", + false => "network/hostname-${::osfamily}.erb", + } + $file_template = pick($hostname_file_template,$hostname_default_template) + $manage_hostname = pick($::network::hostname,$::fqdn) + + if $::osfamily == 'RedHat' { + file { '/etc/sysconfig/network': + ensure => present, + mode => '0644', + owner => 'root', + group => 'root', + content => template($file_template), + notify => $::network::manage_config_file_notify, + } + case $::lsbmajdistrelease { + '7': { + exec { 'sethostname': + command => "/usr/bin/hostnamectl set-hostname ${manage_hostname}", + unless => "/usr/bin/hostnamectl status | grep 'Static hostname: ${manage_hostname}'", + } + } + default: {} + } + } + + if $::osfamily == 'Debian' { + file { '/etc/hostname': + ensure => present, + mode => '0644', + owner => 'root', + group => 'root', + content => template($file_template), + notify => $::network::manage_config_file_notify, + } + } + + if $::osfamily == 'Suse' { + file { '/etc/HOSTNAME': + ensure => present, + mode => '0644', + owner => 'root', + group => 'root', + content => inline_template("<%= @manage_hostname %>\n"), + notify => Exec['sethostname'], + } + exec { 'sethostname': + command => "/bin/hostname ${manage_hostname}", + unless => "/bin/hostname -f | grep ${manage_hostname}", + } + } + + if $::osfamily == 'Solaris' { + file { '/etc/nodename': + ensure => present, + mode => '0644', + owner => 'root', + group => 'root', + content => inline_template("<%= @manage_hostname %>\n"), + notify => Exec['sethostname'], + } + exec { 'sethostname': + command => "/usr/bin/hostname ${manage_hostname}", + unless => "/usr/bin/hostname | /usr/bin/grep ${manage_hostname}", + } + } +} diff --git a/manifests/init.pp b/manifests/init.pp index f2f8326..db1fb18 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,356 +1,268 @@ +# This class manages networking on different Operating systems +# It provives entry points to define, via Hiera data, hashes of +# interfaces, routes, rules and tables. +# The version 4 of this module also introduces backward incompatible +# defines to manage such objects, but allows to use previous style +# syntax by setting to true the telegant legacy params. +# With default settings with class does not manage any resource. + +# @summary Data entrypoint for different network related defines # -# = Class: network +# @param hostname If set the network::hostname class is included and the +# system's hostname configured # -# This class installs and manages network +# @param host_conf_template The .epp or .erb template to use as content +# of the /etc/host.conf file. If undef (as default) the file is not managed. +# @param host_conf_options A custom hash of options to use inside the +# host_conf_template to parametrise values to interpolate. +# In a .epp template refer to them with <%= $options['key'] %> +# In a .erb template refer to them with <%= @host_conf_options['key'] %> # +# @param nsswitch_conf_template The .epp or .erb template to use as content +# of the /etc/nsswitch file. If undef (as default) the file is not managed. +# @param nsswitch_conf_options A custom hash of options to use inside the +# nsswitch_conf_template to parametrise values to interpolate. +# In a .epp template refer to them with <%= $options['key'] %> +# In a .erb template refer to them with <%= @nsswitch_conf_options['key'] %> # -# == Parameters +# @param interfaces_hash An hash of interfaces to configure using the old +# v3 compatible define network::legacy::interface. +# The lookup method is based on the $hiera_merge parameter. +# This is a deprecated parameter used for version 3 backwards compatibility. +# @param interfaces An hash of interfaces to configure. +# This is not actually a class parameter, but a key looked up using the +# merge behaviour configured via the $interfaces_merge_behaviour parameter. +# The define network::interface is declared for each element of this hash. +# @param interfaces_merge_behaviour Defines the lookup method to use to +# retrieve via hiera the $interfaces_hash +# @param interfaces_defaults An hash of default settings to merge with +# the settings of each element of the $interfaces_hash +# Useful to consolidate duplicated data in Hiera. # -# [*gateway*] -# String. Optional. Default: undef -# The default gateway of your system +# @param routes_hash An hash of routes to configure using the old +# v3 compatible define network::legacy::route. +# The lookup method is based on the $hiera_merge parameter. +# This is a deprecated parameter used for version 3 backwards compatibility. +# @param routes An hash of routes to configure. +# This is not actually a class parameter, but a key looked up using the +# merge behaviour configured via $routes_merge_behaviour. +# The define network::route is declared for each element of this hash. +# @param routes_merge_behaviour Defines the lookup method to use to +# retrieve via hiera the $routes_hash +# @param routes_defaults An hash of default settings to merge with +# the settings of each element of the $routes_hash # -# [*hostname*] -# String. Optional. Default: undef -# The hostname of your system +# @param rules_hash An hash of rules to configure using the old +# v3 compatible define network::legacy::rule. +# The lookup method is based on the $hiera_merge parameter. +# This is a deprecated parameter used for version 3 backwards compatibility. +# @param rules An hash of rules to configure. +# This is not actually a class parameter, but a key looked up using the +# merge behaviour configured via $rules_merge_behaviour. +# The define network::rule is declared for each element of this hash. +# @param rules_merge_behaviour Defines the lookup method to use to +# retrieve via hiera the $rules_hash +# @param rules_defaults An hash of default settings to merge with +# the settings of each element of the $rules_hash # -# [*interfaces_hash*] -# Hash. Default undef. -# The complete interfaces configuration (nested) hash -# Needs this structure: -# - First level: Interface name -# - Second level: Interface options (check network::interface for the -# available options) -# If an hash is provided here, network::interface defines are declared with: -# create_resources("network::interface", $interfaces_hash, $default_interfaces_hash) -# -# [*default_interfaces_hash*] -# Hash. Default {}. -# Values applied to all interfaces, if they don't specify a more specific value -# themselves. -# -# [*routes_hash*] -# Hash. Default undef. -# The complete routes configuration (nested) hash -# If an hash is provided here, network::route defines are declared with: -# create_resources("network::route", $routes_hash) -# -# [*mroutes_hash*] -# Hash. Default undef. -# An hash of multiple route to be applied -# If an hash is provided here, network::mroute defines are declared with: -# create_resources("network::mroute", $mroutes_hash) -# -# [*rules_hash*] -# Hash. Default undef. -# An hash of ip rules to be applied -# If an hash is provided here, network::rules defines are declared with: -# create_resources("network::rules", $rules_hash) -# -# [*tables_hash*] -# Hash. Default undef. -# An hash of routing tables to be applied -# If an hash is provided here, network::routing_table defines are declared with: -# create_resources("network::routing_table", $tables_hash) +# @param tables_hash An hash of tables to configure using the old +# v3 compatible define network::legacy::table. +# The lookup method is based on the $hiera_merge parameter. +# This is a deprecated parameter used for version 3 backwards compatibility. +# @param tables An hash of tables to configure. +# This is not actually a class parameter, but a key looked up using the +# merge behaviour configured via $tables_merge_behaviour. +# The define network::table is declared for each element of this hash. +# @param tables_merge_behaviour Defines the lookup method to use to +# retrieve via hiera the $tables_hash +# @param tables_defaults An hash of default settings to merge with +# the settings of each element of the $tables_hash # +# @param service_restart_exec The command to use to restart network +# service when configuration changes occurs. Used with the default +# setting for $config_file_notify +# @param config_file_notify The Resource to trigger when a configuration +# change occurs. Default is Exec[$service_restart_exec], set to undef +# or false or an empty string to not add any notify param on +# config files resources (so no network change is automatically applied) +# Note that if you configure a custom resource reference you must provide it +# in your own profiles. +# @param config_file_per_interface If to configure interfaces in a single file +# or having a single configuration file for each interface. +# Default is true whenever a single file per interface is supported. +# @param hiera_merge If to use hash merge lookup for legacy s_hash +# parameters. +# This is a deprecated parameter used for version 3 backwards compatibility. class network ( - - $hostname = undef, - - $interfaces_hash = undef, - $default_interfaces_hash = {}, - $routes_hash = undef, - $mroutes_hash = undef, - $rules_hash = undef, - $tables_hash = undef, - - $hostname_file_template = "network/hostname-${::osfamily}.erb", - - # Parameter used only on RedHat family - $gateway = undef, - $nozeroconf = undef, - $ipv6enable = undef, - - # Stdmod commons - $package_name = $::network::params::package_name, - $package_ensure = 'present', - - $service_restart_exec = $::network::params::service_restart_exec, - - $config_file_path = $::network::params::config_file_path, - $config_file_require = undef, - $config_file_notify = 'class_default', - $config_file_source = undef, - $config_file_template = undef, - $config_file_content = undef, - $config_file_options_hash = { } , - - $config_file_per_interface = false, - - $config_dir_path = $::network::params::config_dir_path, - $config_dir_source = undef, - $config_dir_purge = false, - $config_dir_recurse = true, - - $dependency_class = undef, - $my_class = undef, - - $monitor_class = undef, - $monitor_options_hash = { } , - - $firewall_class = undef, - $firewall_options_hash = { } , - - $scope_hash_filter = '(uptime.*|timestamp)', - - $tcp_port = undef, - $udp_port = undef, - - $hiera_merge = false, - - ) inherits ::network::params { - - # Hiera import - - if( $hiera_merge == true ) { - $hiera_interfaces_hash = hiera_hash("${module_name}::interfaces_hash",undef) - $real_interfaces_hash = $hiera_interfaces_hash ? { - undef => $interfaces_hash, - default => $hiera_interfaces_hash, - } - - $hiera_routes_hash = hiera_hash('network::routes_hash',undef) - $real_routes_hash = $hiera_routes_hash ? { - undef => $routes_hash, - default => $hiera_routes_hash, - } - - $hiera_mroutes_hash = hiera_hash('network::mroutes_hash',undef) - $real_mroutes_hash = $hiera_mroutes_hash ? { - undef => $mroutes_hash, - default => $hiera_mroutes_hash, - } - $hiera_rules_hash = hiera_hash('network::rules_hash',undef) - $real_rules_hash = $hiera_rules_hash ? { - undef => $rules_hash, - default => $hiera_rules_hash, - } - $hiera_tables_hash = hiera_hash('network::tables_hash',undef) - $real_tables_hash = $hiera_tables_hash ? { - undef => $tables_hash, - default => $hiera_tables_hash, - } - } - else { - $real_interfaces_hash = $interfaces_hash - $real_routes_hash = $routes_hash - $real_mroutes_hash = $mroutes_hash - $real_rules_hash = $rules_hash - $real_tables_hash = $tables_hash + Optional[String] $hostname = undef, + + Optional[String] $host_conf_template = undef, + Hash $host_conf_options = {}, + + Optional[String] $nsswitch_conf_template = undef, + Hash $nsswitch_conf_options = {}, + + Boolean $use_netplan = false, + # This "param" is looked up in code according to interfaces_merge_behaviour + # Optional[Hash] $interfaces = undef, + Enum['first','hash','deep'] $interfaces_merge_behaviour = 'first', + Hash $interfaces_defaults = {}, + + # This "param" is looked up in code according to routes_merge_behaviour + # Optional[Hash] $routes = undef, + Enum['first','hash','deep'] $routes_merge_behaviour = 'first', + Hash $routes_defaults = {}, + + # This "param" is looked up in code according to rules_merge_behaviour + # Optional[Hash] $rules = undef, + Enum['first','hash','deep'] $rules_merge_behaviour = 'first', + Hash $rules_defaults = {}, + + # This "param" is looked up in code according to tables_merge_behaviour + # Optional[Hash] $tables = undef, + Enum['first','hash','deep'] $tables_merge_behaviour = 'first', + Hash $tables_defaults = {}, + + # Legacy Params + Hash $interfaces_hash = {}, + Hash $routes_hash = {}, + Hash $rules_hash = {}, + Hash $tables_hash = {}, + String $service_restart_exec = 'service network restart', + Variant[Resource,String[0,0],Undef,Boolean] $config_file_notify = true, + Variant[Resource,String[0,0],Undef,Boolean] $config_file_require = undef, + Boolean $config_file_per_interface = true, + Boolean $hiera_merge = false, +) { + + $manage_config_file_notify = $config_file_notify ? { + true => "Exec[${service_restart_exec}]", + false => undef, + '' => undef, + undef => undef, + default => $config_file_notify, } - - - # Class variables validation and management - - $config_file_owner = $::network::params::config_file_owner - $config_file_group = $::network::params::config_file_group - $config_file_mode = $::network::params::config_file_mode - - $manage_config_file_content = $config_file_content ? { - undef => $config_file_template ? { - undef => undef, - default => template($config_file_template), - }, - default => $config_file_content, - } - - $manage_config_file_notify = $config_file_notify ? { - 'class_default' => "Exec[${service_restart_exec}]", - 'undef' => undef, - '' => undef, - undef => undef, - default => $config_file_notify, + $manage_config_file_require = $config_file_require ? { + true => undef, + false => undef, + '' => undef, + undef => undef, + default => $config_file_require, } - $manage_hostname = pick($hostname, $::fqdn) - - if $package_ensure == 'absent' { - $config_dir_ensure = absent - $config_file_ensure = absent - } else { - $config_dir_ensure = directory - $config_file_ensure = present + # Exec to restart interfaces + exec { $service_restart_exec : + command => $service_restart_exec, + alias => 'network_restart', + refreshonly => true, + path => $::path, } - - # Dependency class - - if $dependency_class { - include $dependency_class + if $hostname { + contain '::network::hostname' } - - # Resources managed - - if $package_name { - package { 'network': - ensure => $package_ensure, - name => $package_name, + # Manage /etc/host.conf if $host_conf_template is set + if $host_conf_template { + $host_conf_template_type=$host_conf_template[-4,4] + $host_conf_content = $host_conf_template_type ? { + '.epp' => epp($host_conf_template,{ options => $host_conf_options }), + '.erb' => template($host_conf_template), + default => template($host_conf_template), } - Package['network'] -> Network::Interface<||> - Package['network'] -> Network::Route<||> - Package['network'] -> Network::Mroute<||> - Package['network'] -> Network::Rule<||> - Package['network'] -> Network::Routing_table<||> - } - - if $config_file_path - and $config_file_source - or $manage_config_file_content { - file { 'network.conf': - ensure => $config_file_ensure, - path => $config_file_path, - mode => $config_file_mode, - owner => $config_file_owner, - group => $config_file_group, - source => $config_file_source, - content => $manage_config_file_content, + file { '/etc/host.conf': + ensure => present, + content => $host_conf_content, notify => $manage_config_file_notify, - require => $config_file_require, } } - if $config_dir_source { - file { 'network.dir': - ensure => $config_dir_ensure, - path => $config_dir_path, - source => $config_dir_source, - recurse => $config_dir_recurse, - purge => $config_dir_purge, - force => $config_dir_purge, + # Manage /etc/nsswitch.conf if $nsswitch_conf_template is set + if $nsswitch_conf_template { + $nsswitch_conf_template_type=$nsswitch_conf_template[-4,4] + $nsswitch_conf_content = $nsswitch_conf_template_type ? { + '.epp' => epp($nsswitch_conf_template,{ options => $nsswitch_conf_options}), + '.erb' => template($nsswitch_conf_template), + default => template($nsswitch_conf_template), + } + file { '/etc/nsswitch.conf': + ensure => present, + content => $nsswitch_conf_content, notify => $manage_config_file_notify, - require => $config_file_require, } } - # Command that triggers network restart - exec { $service_restart_exec : - command => $service_restart_exec, - alias => 'network_restart', - refreshonly => true, - path => '/bin:/sbin:/usr/bin:/usr/sbin', - } - - # Create network interfaces from interfaces_hash, if present - - if $real_interfaces_hash { - create_resources('network::interface', $real_interfaces_hash, $default_interfaces_hash) + # Declare network interfaces based on network::interfaces + $interfaces = lookup('network::interfaces',Hash,$interfaces_merge_behaviour,{}) + $interfaces.each |$k,$v| { + network::interface { $k: + * => $interfaces_defaults + $v, + } } - - if $real_routes_hash { - create_resources('network::route', $real_routes_hash) + # Declare network::legacy::interface based on legacy network::interfaces_hash + $legacy_interfaces_hash = $hiera_merge ? { + true => lookup('network::interfaces_hash',Hash,'hash',{}), + false => $interfaces_hash, } - - if $real_mroutes_hash { - create_resources('network::mroute', $real_mroutes_hash) + $legacy_interfaces_hash.each |$k,$v| { + network::legacy::interface { $k: + * => $interfaces_defaults + $v, + } } - if $real_rules_hash { - create_resources('network::rule', $real_rules_hash) + # Declare network routes based on network::routes + $routes = lookup('network::routes',Hash,$routes_merge_behaviour,{}) + $routes.each |$k,$v| { + network::route { $k: + * => $routes_defaults + $v, + } } - - if $real_tables_hash { - create_resources('network::routing_table', $real_tables_hash) + # Declare network::legacy::route based on legacy network::routes_hash + $legacy_routes_hash = $hiera_merge ? { + true => lookup('network::routes_hash',Hash,'hash',{}), + false => $routes_hash, } - - # Configure default gateway (On RedHat). Also hostname is set. - if $::osfamily == 'RedHat' - and ($::network::gateway - or $::network::hostname) { - file { '/etc/sysconfig/network': - ensure => $config_file_ensure, - mode => $config_file_mode, - owner => $config_file_owner, - group => $config_file_group, - content => template($network::hostname_file_template), - notify => $network::manage_config_file_notify, - } - case $::lsbmajdistrelease { - '7': { - exec { 'sethostname': - command => "/usr/bin/hostnamectl set-hostname ${manage_hostname}", - unless => "/usr/bin/hostnamectl status | grep 'Static hostname: ${manage_hostname}'", - } - } - default: {} + $legacy_routes_hash.each |$k,$v| { + network::legacy::route { $k: + * => $routes_defaults + $v, } } - # Configure hostname (On Debian) - if $::osfamily == 'Debian' - and $hostname { - file { '/etc/hostname': - ensure => $config_file_ensure, - mode => $config_file_mode, - owner => $config_file_owner, - group => $config_file_group, - content => template($hostname_file_template), - notify => $manage_config_file_notify, - } - } - if $::osfamily == 'Suse' { - if $hostname { - file { '/etc/HOSTNAME': - ensure => $config_file_ensure, - mode => $config_file_mode, - owner => $config_file_owner, - group => $config_file_group, - content => inline_template("<%= @manage_hostname %>\n"), - notify => Exec['sethostname'], - } - exec { 'sethostname': - command => "/bin/hostname ${manage_hostname}", - unless => "/bin/hostname -f | grep ${manage_hostname}", - } + # Declare network rules based on network::rules + $rules = lookup('network::rules',Hash,$rules_merge_behaviour,{}) + $rules.each |$k,$v| { + network::rule { $k: + * => $rules_defaults + $v, } } - - if $::osfamily == 'Solaris' { - if $hostname { - file { '/etc/nodename': - ensure => $config_file_ensure, - mode => $config_file_mode, - owner => $config_file_owner, - group => $config_file_group, - content => inline_template("<%= @manage_hostname %>\n"), - notify => Exec['sethostname'], - } - exec { 'sethostname': - command => "/usr/bin/hostname ${manage_hostname}", - unless => "/usr/bin/hostname | /usr/bin/grep ${manage_hostname}", - } + # Declare network::legacy::rule based on legacy network::rules_hash + $legacy_rules_hash = $hiera_merge ? { + true => lookup('network::rules_hash',Hash,'hash',{}), + false => $rules_hash, + } + $legacy_rules_hash.each |$k,$v| { + network::legacy::rule { $k: + * => $rules_defaults + $v, } } - # Extra classes - - if $network::my_class { - include $network::my_class - } - - if $network::monitor_class { - class { $network::monitor_class: - options_hash => $network::monitor_options_hash, - scope_hash => {}, # TODO: Find a good way to inject class' scope + # Declare network tables based on network::tables + $tables = lookup('network::tables',Hash,$tables_merge_behaviour,{}) + $tables.each |$k,$v| { + network::table { $k: + * => $tables_defaults + $v, } } - - if $firewall_class { - class { $firewall_class: - options_hash => $firewall_options_hash, - scope_hash => {}, + # Declare network::legacy::table based on legacy network::tables_hash + $legacy_tables_hash = $hiera_merge ? { + true => lookup('network::tables_hash',Hash,'hash',{}), + false => $tables_hash, + } + $legacy_tables_hash.each |$k,$v| { + network::legacy::table { $k: + * => $tables_defaults + $v, } } diff --git a/manifests/interface.pp b/manifests/interface.pp index 4b865c5..1bd573a 100644 --- a/manifests/interface.pp +++ b/manifests/interface.pp @@ -1,805 +1,464 @@ -# -# = Define: network::interface -# -# This define manages interfaces. -# Currently only Debian and RedHat families supported. -# Some parameters are supported only for specific families -# -# == Common parameters -# -# $enable_dhcp -# Boolean. Default: false -# Activates DHCP on the interface -# -# [*ipaddress*] -# [*netmask*] -# [*broadcast*] -# [*hwaddr*] -# String. Default: undef -# Standard network parameters -# -# [*enable*] -# Boolean. Default: true -# Manages the interface presence. Possible values: -# * true - Interface created and enabled at boot. -# * false - Interface removed from boot. -# -# [*template*] -# String. Optional. Default: Managed by module. -# Provide an alternative custom template to use for configuration of: -# - On Debian: file fragments in /etc/network/interfaces -# - On RedHat: files /etc/sysconfig/network-scripts/ifcfg-${name} -# You can copy and adapt network/templates/interface/${::osfamily}.erb -# -# [*restart_all_nic*] -# Boolean. Default: true -# Manages the way to apply interface creation/modification: -# - If true, will trigger a restart of all network interfaces -# - If false, will only start/restart this specific interface -# -# [*reload_command*] -# String. Default: $::operatingsystem ? {'CumulusLinux' => 'ifreload -a', -# default => "ifdown ${interface}; ifup ${interface}", -# } -# Defines the command(s) that will be used to reload a nic when restart_all_nic -# is set to false -# -# [*options*] -# A generic hash of custom options that can be used in a custom template -# -# [*options_extra_redhat*] -# [*options_extra_debian*] -# [*options_extra_suse*] -# Custom hashes of options that are added to the default template that manages -# interfaces respectively under RedHat, Debian and Suse families -# -# [*description*] -# String. Optional. Default: undef -# Adds comment with given description in file before interface declaration. -# -# == Debian only parameters -# -# $address = undef, -# Both ipaddress (standard name) and address (Debian param name) if set -# configure the ipv4 address of the interface. -# If both are present address is used. -# Note, that if $my_inner_ipaddr (for GRE) is set - it is used instead. -# -# $manage_order = 10, -# This is used by concat to define the order of your fragments, -# can be used to load an interface before another. -# default it's 10. -# -# $method = '', -# Both enable_dhcp (standard) and method (Debian specific param name) if set -# configure dhcp on the interface via the method setting. -# If both are present method is used. -# -# $up = [ ], -# $pre_up = [ ], -# $post_up = [ ], -# $down = [ ], -# $pre_down = [ ], -# $post_down = [ ], -# Map to Debian interfaces parameters (with _ instead of -) -# Note that these params MUST be arrays, even if with only one element -# -# $nonlocal_gateway = undef, -# Gateway, that does not belong to interface's network and needs extra -# route to be available. Shortcut for: -# -# post-up ip route add $nonlocal_gateway dev $interface -# post-up ip route add default via $nonlocal_gateway dev $interface -# pre-down ip route del default via $nonlocal_gateway dev $interface -# pre-down ip route del $nonlocal_gateway dev $interface -# -# $additional_networks = [], -# Convenience shortcut to add more networks to the interface. Expands to: -# -# up ip addr add $network dev $interface -# down ip addr del $network dev $interface -# -# Check the arguments in the code for the other Debian specific settings -# If defined they are set in the used template. -# -# == RedHat only parameters -# -# $type = 'Ethernet', -# Defaults to 'Ethernet', but following types are supported for OVS: -# "OVSPort", "OVSIntPort", "OVSBond", "OVSTunnel" and "OVSPatchPort". -# 'InfiniBand' type is supported as well. -# -# $ipaddr = undef, -# Both ipaddress (standard name) and ipaddr (RedHat param name) if set -# configure the ipv4 address of the interface. -# If both are present ipaddr is used. -# -# $hwaddr = undef, -# hwaddr if set configures the mac address of the interface. -# -# $prefix = undef, -# Network PREFIX aka CIDR notation of the network mask. The PREFIX -# takes precedence if both PREFIX and NETMASK are set. -# -# $bootproto = '', -# Both enable_dhcp (standard) and bootproto (Debian specific param name), -# if set, configure dhcp on the interface via the bootproto setting. -# If both are present bootproto is used. -# -# $arpcheck = undef -# Whether the interface will check if the supplied IP address is already in -# use. Valid values are undef, "yes", "no". -# -# $arp = undef -# Used to enable or disable ARP completely for an interface at initialization -# Valid values are undef, "yes", "no". -# -# $nozeroconf = undef -# Used to enable or disable ZEROCONF routes completely for an -# interface at initialization -# Valid values are undef, "yes, 'no". -# -# $linkdelay = undef -# Used to introduce a delay (sleep) of the specified number of seconds when -# bringing an interface up. -# -# $check_link_down = false -# Set to true to add check_link_down function in the interface file -# -# $hotswap = undef -# Set to no to prevent interface from being activated when hot swapped - Default is yes -# -# $vid = undef -# Set to specify vlan id # -# -# == RedHat and Debian only GRE interface specific parameters -# -# $peer_outer_ipaddr = undef -# IP address of the remote tunnel endpoint -# -# $peer_inner_ipaddr = undef -# IP address of the remote end of the tunnel interface. If this is specified, -# a route to PEER_INNER_IPADDR through the tunnel is added automatically. -# -# $my_outer_ipaddr = undef -# IP address of the local tunnel endpoint. If unspecified, an IP address -# is selected automatically for outgoing tunnel packets, and incoming tunnel -# packets are accepted on all local IP addresses. -# -# $my_inner_ipaddr = undef -# Local IP address of the tunnel interface. -# -# == RedHat only Open vSwitch specific parameters -# -# $devicetype = undef, -# Always set to "ovs" if configuring OVS* type. -# -# $bond_ifaces = undef, -# Physical interfaces for "OVSBond". -# -# $ovs_bridge = undef, -# For types other than "OVSBridge" type. It specifies the OVS bridge -# to which port, patch or tunnel should be attached to. -# -# $ovs_ports = undef, -# It specifies the OVS ports should OVS bridge attach -# -# $ovs_extra = undef, -# Optional: extra ovs-vsctl commands seperate by "--" (double dash) -# -# $ovs_options = undef, -# Optional: extra options to set in the Port table. -# Check ovs-vsctl's add-port man page. -# -# $ovs_patch_peer = undef, -# Patche's peer on the other bridge for "OVSPatchPort" type. -# -# $ovs_tunnel_type = undef, -# Tunnel types (eg. "vxlan", "gre") for "OVSTunnel" type. -# -# $ovs_tunnel_options = undef, -# Tunnel options (eg. "remote_ip") for "OVSTunnel" type. -# -# $ovsdhcpinterfaces = undef, -# All the interfaces that can reach the DHCP server as a space separated list -# -# $ovsbootproto = undef, -# Needs OVSBOOTPROTO instead of BOOTPROTO to enable DHCP on the bridge -# -# Check the arguments in the code for the other RedHat specific settings -# If defined they are set in the used template. -# -# == RedHat only InfiniBand specific parameters -# -# $connected_mode = undef, -# Enable or not InfiniBand CONNECTED_MODE. It true, CONNECTED_MODE=yes will -# be added to ifcfg file. -# -# == Suse and Debian only parameters -# -# $aliases = undef -# Array of aliased IPs for given interface. -# Note, that for Debian generated interfaces will have static method and -# netmask 255.255.255.255. If you need something other - generate -# interfaces by hand. Also note, that interfaces will be named -# $interface:$idx, where $idx is IP index in list, starting from 0. -# If you're adding manual interfaces - beware of clashes. -# -# == Suse only parameters -# -# Check the arguments in the code for the other Suse specific settings -# If defined they are set in the used template. -# -# -# == Red Hat zLinux on IBM ZVM/System Z (s390/s390x) only parameters -# -# $subchannels = undef, -# The hardware addresses of QETH or Hipersocket hardware. -# -# $nettype = undef, -# The networking hardware type. qeth, lcs or ctc. -# The default is 'qeth'. -# -# $layer2 = undef, -# The networking layer mode in Red Hat 6. 0 or 1. -# The defauly is 0. From Red Hat 7 this is confifured using the options -# parameter below. -# -# $zlinux_options = undef -# You can add any valid sysfs attribute and its value to the OPTIONS -# parameter.The Red Hat Enterprise Linux (7 )installation program currently -# uses this to configure the layer mode (layer2) and the relative port -# number (portno) of qeth devices. +# This define manages network interfaces on different operating systems. +# It provides some default configurations that can be overridden via relevant +# parameters. +# +# @summary A define to manage network interfaces +# +# @example Configure an interface to use DHCP +# network::interface { 'eth0': +# enable_dhcp => true, +# } +# +# @example Configure an interface with a given IP address +# network::interface { 'eth0': +# ipv4_address => 10.42.42.42, +# ipv4_netmask => 255.255.255.0, +# } +# +# @param ensure If to create or remove the relevant configuration file. +# @param template The epp or erb template to use for the interface configuration +# file. Default is automatically defined based on $::osfamily, +# @param config_path The path of the interface configuration file. +# Default is automatically defined based on the Operating System. +# @param enable_dhcp If to configure the interface to use dhcp. +# @param interface The name of the interface to use. Default value is the $title of +# the define. Can be set explicitly in case different title names have to +# used. +# @param description A free text description to use, where applicable, to describe +# the interface. It has no real effect on the interface configuration. +# @param ipv4_address The optional IPv4 address of the interface. +# @param ipv4_netmask The optional netmask of the IPv4 address. +# @param ipv4_network The optional IPv4 network address. +# @param ipv4_broadcast The optional IPv4 broadcast address. +# @param ipv6_address The optional IPv6 address of the interface. +# @param ipv6_netmask The optional netmask of the IPv6 address. +# @param ipv6_network The optional IPv6 network address. +# @param mtu The interface Maximum Transmission Unit (in bytes). +# @param mac The (optional) interface MAC address. +# @param redhat_extra_settings A free hash of custom settings to +# add to the interface configuration. Used only on redhat family nodes. +# @param redhat_extra_header A custom free text to add as header +# to the interface configuration file on RedHat family nodes. +# @param redhat_extra_footer A custom free text to add as footer +# to the interface configuration file on RedHat family nodes. +# @param debian_extra_settings Equivalent of redhat_extra_settings for Debian osfamily. +# @param debian_extra_header Equivalent of redhat_extra_header for Debian osfamily. +# @param debian_extra_footer Equivalent of redhat_extra_footer for Debian osfamily. +# @param suse_extra_settings Equivalent of redhat_extra_settings for Suse osfamily. +# @param suse_extra_header Equivalent of redhat_extra_header for Suse osfamily. +# @param suse_extra_footer Equivalent of redhat_extra_footer for Suse osfamily. +# @param solaris_extra_settings Equivalent of redhat_extra_settings for Solaris. +# @param solaris_extra_header Equivalent of redhat_extra_header for Solaris. +# @param solaris_extra_footer Equivalent of redhat_extra_footer for Solaris. +# @param use_default_settings If to use some default settings also based on $os_features +# to correctly configure interface files. They can be overridden via the +# osfamily extra_settings. +# @param os_features Some features which affect the default_settings. +# @param config_file_notify The Resource to trigger when a configuration +# change occurs. Default is what is se in $:::network::config_file_notify +# @param manage_prerequisites If to automatically manage prerequisite resources +# like packages when needed by the interface type +# @suppress_warnings If not avoid to display notify warnings for unsupported OS. define network::interface ( + Enum['present','absent'] $ensure = 'present', + Boolean $enable = true, + Boolean $use_netplan = lookup('network::use_netplan',Boolean,first,false), - $enable = true, - $ensure = 'present', - $template = "network/interface/${::osfamily}.erb", - $options = undef, - $options_extra_redhat = undef, - $options_extra_debian = undef, - $options_extra_suse = undef, - $interface = $name, - $restart_all_nic = true, - $reload_command = undef, - - $enable_dhcp = false, - - $ipaddress = '', - $netmask = undef, - $network = undef, - $broadcast = undef, - $gateway = undef, - $hwaddr = undef, - $mtu = undef, - - $description = undef, - - ## Debian specific - $manage_order = '10', - $auto = true, - $allow_hotplug = undef, - $method = '', - $family = 'inet', - $stanza = 'iface', - $address = '', - $dns_search = undef, - $dns_nameservers = undef, - # For method: static - $metric = undef, - $pointopoint = undef, - - # For method: dhcp - $hostname = undef, - $leasehours = undef, - $leasetime = undef, - $client = undef, - - # For method: bootp - $bootfile = undef, - $server = undef, - - # For method: tunnel - $mode = undef, - $endpoint = undef, - $dstaddr = undef, - $local = undef, - $ttl = undef, - - # For method: ppp - $provider = undef, - $unit = undef, - - # For inet6 family - $privext = undef, - $dhcp = undef, - $media = undef, - $accept_ra = undef, - $autoconf = undef, - $vlan_raw_device = undef, - - # Convenience shortcuts - $nonlocal_gateway = undef, - $additional_networks = [ ], - - # Common ifupdown scripts - $up = [ ], - $pre_up = [ ], - $post_up = [ ], - $down = [ ], - $pre_down = [ ], - $post_down = [ ], - - # For virtual routing and forwarding (VRF) - $vrf = undef, - $vrf_table = undef, - - # For bonding - $slaves = [ ], - $bond_mode = undef, - $bond_miimon = undef, - $bond_downdelay = undef, - $bond_updelay = undef, - $bond_lacp_rate = undef, - $bond_master = undef, - $bond_primary = undef, - $bond_slaves = [ ], - $bond_xmit_hash_policy = undef, - $bond_num_grat_arp = undef, - $bond_arp_all = undef, - $bond_arp_interval = undef, - $bond_arp_iptarget = undef, - $bond_fail_over_mac = undef, - $bond_ad_select = undef, - $use_carrier = undef, - $primary_reselect = undef, + String $template = "network/interface/${::osfamily}.epp", + Optional[String] $config_path = undef, - # For teaming - $team_config = undef, - $team_port_config = undef, - $team_master = undef, - # For bridging - $bridge_ports = [ ], - $bridge_stp = undef, - $bridge_fd = undef, - $bridge_maxwait = undef, - $bridge_waitport = undef, + String $interface = $title, + String $description = "Interface ${title}", - # For wpa_supplicant - $wpa_ssid = undef, - $wpa_bssid = undef, - $wpa_psk = undef, - $wpa_key_mgmt = [ ], - $wpa_group = [ ], - $wpa_pairwise = [ ], - $wpa_auth_alg = [ ], - $wpa_proto = [ ], - $wpa_identity = undef, - $wpa_password = undef, - $wpa_scan_ssid = undef, - $wpa_ap_scan = undef, + Boolean $ipv4_dhcp = false, + Optional[Stdlib::IP::Address::V4] $ipv4_address = undef, + Optional[Stdlib::IP::Address::V4] $ipv4_netmask = undef, + Optional[Stdlib::IP::Address::V4] $ipv4_network = undef, + Optional[Stdlib::IP::Address::V4] $ipv4_broadcast = undef, + Optional[Stdlib::IP::Address::V4] $ipv4_gateway = undef, + Optional[Integer] $ipv4_mtu = undef, - ## RedHat specific - $ipaddr = '', - $prefix = undef, - $uuid = undef, - $bootproto = '', - $userctl = 'no', - $type = 'Ethernet', - $ethtool_opts = undef, - $ipv6init = undef, - $ipv6_autoconf = undef, - $ipv6_privacy = undef, - $ipv6_addr_gen_mode = undef, - $ipv6addr = undef, - $ipv6addr_secondaries = [], - $ipv6_defaultgw = undef, - $dhcp_hostname = undef, - $srcaddr = undef, - $peerdns = '', - $peerntp = '', - $onboot = '', - $onparent = undef, - $defroute = undef, - $dns1 = undef, - $dns2 = undef, - $dns3 = undef, - $domain = undef, - $nm_controlled = undef, - $master = undef, - $slave = undef, - $bonding_master = undef, - $bonding_opts = undef, - $vlan = undef, - $vlan_name_type = undef, - $vlan_id = undef, - $vid = undef, - $physdev = undef, - $bridge = undef, - $arpcheck = undef, - $zone = undef, - $arp = undef, - $nozeroconf = undef, - $linkdelay = undef, - $check_link_down = false, - $hotplug = undef, - $persistent_dhclient = undef, - $nm_name = undef, + Boolean $ipv6_dhcp = false, + Optional[Stdlib::IP::Address::V6] $ipv6_address = undef, + Optional[Stdlib::IP::Address::V6] $ipv6_netmask = undef, + Optional[Stdlib::IP::Address::V6] $ipv6_network = undef, + Optional[Stdlib::IP::Address::V6] $ipv6_gateway = undef, + Optional[Integer] $ipv6_mtu = undef, - # RedHat specific for InfiniBand - $connected_mode = undef, + Optional[Integer] $mac = undef, + Boolean $mac_override = false, - # RedHat specific for GRE - $peer_outer_ipaddr = undef, - $peer_inner_ipaddr = undef, - $my_outer_ipaddr = undef, - $my_inner_ipaddr = undef, + Hash $redhat_extra_settings = {}, + Optional[String] $redhat_extra_header = undef, + Optional[String] $redhat_extra_footer = undef, - # RedHat and Debian specific for Open vSwitch - $devicetype = undef, # On RedHat. Same of ovs_type for Debian - $bond_ifaces = undef, # On RedHat Same of ovs_bonds for Debian - $ovs_type = undef, # Debian - $ovs_bonds = undef, # Debian - $ovs_bridge = undef, - $ovs_ports = undef, - $ovs_extra = undef, - $ovs_options = undef, - $ovs_patch_peer = undef, - $ovsrequires = undef, - $ovs_tunnel_type = undef, - $ovs_tunnel_options = undef, - $ovsdhcpinterfaces = undef, - $ovsbootproto = undef, + Hash $debian_extra_settings = {}, + Optional[String] $debian_extra_header = undef, + Optional[String] $debian_extra_footer = undef, - # RedHat specific for zLinux - $subchannels = undef, - $nettype = undef, - $layer2 = undef, - $zlinux_options = undef, + Hash $suse_extra_settings = {}, + Optional[String] $suse_extra_header = undef, + Optional[String] $suse_extra_footer = undef, - ## Suse specific - $startmode = '', - $usercontrol = 'no', - $firewall = undef, - $aliases = undef, - $remote_ipaddr = undef, - $check_duplicate_ip = undef, - $send_gratuitous_arp = undef, - $pre_up_script = undef, - $post_up_script = undef, - $pre_down_script = undef, - $post_down_script = undef, + Hash $solaris_extra_settings = {}, + Optional[String] $solaris_extra_header = undef, + Optional[String] $solaris_extra_footer = undef, - # For bonding - $bond_moduleopts = undef, - # also used for Suse bonding: $bond_master, $bond_slaves + Boolean $use_default_settings = true, - # For bridging - $bridge_fwddelay = undef, - # also used for Suse bridging: $bridge, $bridge_ports, $bridge_stp + Array $os_features = ['check_link_down','auto'], - # For vlan - $etherdevice = undef, - # also used for Suse vlan: $vlan + Variant[Undef,Resource,String] $config_file_notify = 'class_default', + Boolean $config_file_per_interface = true, - ) { + Boolean $manage_prerequisites = true, + Boolean $suppress_warnings = false, +) { - include ::network - - validate_bool($auto) - validate_bool($enable) - validate_bool($restart_all_nic) - - validate_array($up) - validate_array($pre_up) - validate_array($down) - validate_array($pre_down) - validate_array($slaves) - validate_array($bond_slaves) - validate_array($bridge_ports) - validate_array($wpa_key_mgmt) - validate_array($wpa_group) - validate_array($wpa_pairwise) - validate_array($wpa_auth_alg) - validate_array($wpa_proto) - - # $subchannels is only valid for zLinux/SystemZ/s390x. - if $::architecture == 's390x' { - validate_array($subchannels) - validate_re($nettype, '^(qeth|lcs|ctc)$', "${name}::\$nettype may be 'qeth', 'lcs' or 'ctc' only and is set to <${nettype}>.") - # Different parameters required for RHEL6 and RHEL7 - if $::operatingsystemmajrelease =~ /^7/ { - validate_string($zlinux_options) - } else { - validate_re($layer2, '^0|1$', "${name}::\$layer2 must be 1 or 0 and is to <${layer2}>.") + case fact('os.family') { + 'RedHat': { + if 'check_link_down' in $os_features { + $os_footer = @("EOF") + check_link_down() { + return 1; + } + |- EOF + } else { + $os_footer = '' + } + $os_header = '' + $os_settings = { + 'ONBOOT' => $enable ? { + true => 'yes', + false => 'yes', + }, + 'BOOTPROTO' => $ipv4_dhcp ? { + true => 'dhcp', + false => 'none', + }, + 'DEVICE' => $interface, + 'IPADDR' => $ipv4_address, + 'NETWORK' => $ipv4_network, + 'NETMASK' => $ipv4_netmask, + 'BROADCAST' => $ipv4_broadcast, + 'GATEWAY' => $ipv4_gateway, + 'MTU' => $ipv4_mtu, + 'HWADDR' => $mac_override ? { + true => undef, + default => $mac, + }, + 'MACADDR' => $mac_override ? { + true => $mac, + default => undef, + }, + 'DHCPV6C' => $ipv6_dhcp ? { + true => 'yes', + false => undef, + }, + 'IPV6ADDR' => $ipv6_address, + 'IPV6MTU' => $ipv6_mtu, + 'IPV6INIT' => $ipv6_dhcp ? { + true => 'yes', + false => $ipv6_address ? { + undef => undef, + default => 'yes', + }, + }, + } + $extra_settings = $redhat_extra_settings + $extra_header = $redhat_extra_header + $extra_footer = $redhat_extra_footer } + 'Debian': { + $debian_method = $ipv4_dhcp ? { + true => 'dhcp', + false => 'static', + } + $os_header = "iface ${interface} inet ${debian_method}\n" + $os_footer = '' + $os_settings = { + address => $ipv4_address, + netmask => $ipv4_netmask, + } + $extra_settings = $debian_extra_settings + $extra_header = $debian_extra_header + $extra_footer = $debian_extra_footer + } + 'SuSE': { + $os_header = '' + $os_footer = '' + $os_settings = { + 'STARTMODE' => $enable ? { + true => 'auto', + false => 'off', + }, + 'BOOTPROTO' => $ipv4_dhcp ? { + true => 'dhcp', + false => 'static', + }, + 'DEVICE' => $interface, + 'IPADDR' => $ipv4_address, + 'NETWORK' => $ipv4_network, + 'NETMASK' => $ipv4_netmask, + 'BROADCAST' => $ipv4_broadcast, + 'GATEWAY' => $ipv4_gateway, + 'MTU' => $ipv4_mtu, + 'LLADDR' => $mac, + } + $extra_settings = $suse_extra_settings + $extra_header = $suse_extra_header + $extra_footer = $suse_extra_footer + } + 'Solaris': { + $os_header = '' + $os_footer = '' + $os_settings = {} + $extra_settings = $solaris_extra_settings + $extra_header = $solaris_extra_header + $extra_footer = $solaris_extra_footer + } + default: {} } - if $arp != undef and ! ($arp in ['yes', 'no']) { - fail('arp must be one of: undef, yes, no') - } - - if $arpcheck != undef and ! ($arpcheck in ['yes', 'no']) { - fail('arpcheck must be one of: undef, yes, no') - } - - if $nozeroconf != undef and ! ($nozeroconf in ['yes', 'no']) { - fail('nozeroconf must be one of: undef, yes, no') - } - - if $check_duplicate_ip != undef and ! ($check_duplicate_ip in ['yes', 'no']) { - fail('check_duplicate_ip must be one of: undef, yes, no') - } - - if $send_gratuitous_arp != undef and ! ($send_gratuitous_arp in ['yes', 'no']) { - fail('send_gratuitous_arp must be one of: undef, yes, no') - } - - if $::osfamily != 'RedHat' and ($type == 'InfiniBand' or $connected_mode) { - fail('InfiniBand parameters are supported only for RedHat family.') - } - - if $type != 'InfiniBand' and $connected_mode != undef { - fail('CONNECTED_MODE parameter available for InfiniBand interfaces only') - } - - if $prefix != undef and $netmask != undef { - fail('Use either netmask or prefix to define the netmask for the interface') - } - $manage_hwaddr = $hwaddr ? { - default => $hwaddr, + # $settings variable is used in templates + if $use_default_settings { + $settings = delete_undef_values($os_settings + $extra_settings) + $header = "${os_header}${extra_header}" + $footer = "${os_footer}${extra_footer}" + } else { + $settings = delete_undef_values($extra_settings) + $header = $extra_header + $footer = $extra_footer } - $manage_method = $method ? { - '' => $enable_dhcp ? { - true => 'dhcp', - false => 'static', - }, - default => $method, + $params = { + settings => $settings, + header => $header, + footer => $footer, + interface => $interface, + description => $description, } - # Debian specific - case $manage_method { - 'auto': { $manage_address = undef } - 'bootp': { $manage_address = undef } - 'dhcp': { $manage_address = undef } - 'ipv4ll': { $manage_address = undef } - 'loopback': { $manage_address = undef } - 'manual': { $manage_address = undef } - 'none': { $manage_address = undef } - 'ppp': { $manage_address = undef } - 'wvdial': { $manage_address = undef } + # Content used in interface configuration file + $template_type=$template[-4,4] + case $template_type { + '.epp': { + $content = epp($template, { params => $params } ) + } + '.erb': { + $content = template($template) + } default: { - $manage_address = $my_inner_ipaddr ? { - undef => $address ? { - '' => $ipaddress, - default => $address, - }, - default => $my_inner_ipaddr, + # If no known extension is present, we treat $template as an erb template + $content = template($template) + } + } + # Configuration file path + case fact('os.family') { + 'RedHat': { + $config_file_path = pick($config_path,"/etc/sysconfig/network-scripts/ifcfg-${title}") + } + 'Suse': { + $config_file_path = pick($config_path,"/etc/sysconfig/network/ifcfg-${title}") + } + 'Debian': { + if fact('os.name') == 'CumulusLinux' { + $config_file_path = pick($config_path,"/etc/network/interfaces.d/${title}") + } else { + $config_file_path = pick($config_path,"/etc/network/interfaces.d/${title}.cfg") } } + 'Solaris': { + $config_file_path = pick($config_path,"/etc/hostname.${title}") + } + default: {} } - # Redhat and Suse specific - if $::operatingsystem == 'SLES' and versioncmp($::operatingsystemrelease, 12) >= 0 { - $bootproto_false = 'static' - } else { - $bootproto_false = 'none' + # Define how to restart network service + $real_config_file_notify = $config_file_notify ? { + 'class_default' => $::network::manage_config_file_notify, + default => $config_file_notify, } - $manage_bootproto = $bootproto ? { - '' => $enable_dhcp ? { - true => 'dhcp', - false => $bootproto_false - }, - default => $bootproto, - } - $manage_peerdns = $peerdns ? { - '' => $manage_bootproto ? { - 'dhcp' => 'yes', - default => 'no', - }, - true => 'yes', - false => 'no', - default => $peerdns, - } - $manage_peerntp = $peerntp ? { - '' => $manage_bootproto ? { - 'dhcp' => 'yes', - default => 'no', - }, - default => $peerntp, - } - $manage_ipaddr = $ipaddr ? { - '' => $ipaddress, - default => $ipaddr, - } - $manage_onboot = $onboot ? { - '' => $enable ? { - true => 'yes', - false => 'no', - }, - default => $onboot, - } - $manage_defroute = $defroute ? { - true => 'yes', - false => 'no', - default => $defroute, - } - $manage_startmode = $startmode ? { - '' => $enable ? { - true => 'auto', - false => 'off', - }, - default => $startmode, - } - # Resources - $real_reload_command = $reload_command ? { - undef => $::operatingsystem ? { - 'CumulusLinux' => 'ifreload -a', - default => "ifdown ${interface} --force ; ifup ${interface}", - }, - default => $reload_command, - } - if $restart_all_nic == false and $::kernel == 'Linux' { - exec { "network_restart_${name}": - command => $real_reload_command, - path => '/sbin', - refreshonly => true, - } - $network_notify = "Exec[network_restart_${name}]" - } else { - $network_notify = $network::manage_config_file_notify - } + ### Manage configurations + case fact('os.name') { - case $::osfamily { + # On RedHat family we manage "/etc/sysconfig/network-scripts/ifcfg-${title}" + 'RedHat', 'CentOS', 'Scientific', 'OracleLinux','Fedora': { + # Configuration + file { $config_file_path: + ensure => $ensure, + content => $content, + mode => '0644', + owner => 'root', + group => 'root', + notify => $real_config_file_notify, + } + } - 'Debian': { - if $vlan_raw_device { - if versioncmp('9.0', $::operatingsystemrelease) >= 0 + # On Suse family we manage "/etc/sysconfig/network/ifcfg-${title}" + 'SLES', 'OpenSuSE': { + # Prerequisites + if $manage_prerequisites + and is_hash($extra_params) { + if has_key($extra_params,'VLAN_ID') and !defined(Package['vlan']) { package { 'vlan': ensure => 'present', } + Package['vlan'] -> File[$config_file_path] + } + } + if $manage_prerequisites + and has_key($settings,'BRIDGE') + and !defined(Package['bridge-utils']) { + package { 'bridge-utils': + ensure => 'present', } + Package['bridge-utils'] -> File[$config_file_path] + } + # Configuration + file { $config_file_path: + ensure => $ensure, + content => $content, + mode => '0600', + owner => 'root', + group => 'root', + notify => $real_config_file_notify, } + } - if $network::config_file_per_interface { - if ! defined(File['/etc/network/interfaces.d']) { - file { '/etc/network/interfaces.d': - ensure => 'directory', - mode => '0755', - owner => 'root', - group => 'root', - } + # On Debian family we manage "/etc/network/interfaces.d/${title}.cfg" + # or lines in /etc/sysconfig/network according to the value of + # $::network::config_file_per_interface + 'Debian', 'Ubuntu', 'LinuxMint': { + # Prerequisites + if $manage_prerequisites + and has_key($settings,'vlan-raw-device') + and versioncmp('9.0', $::operatingsystemrelease) >= 0 + and !defined(Package['vlan']) { + package { 'vlan': + ensure => 'present', } - if $::operatingsystem == 'CumulusLinux' { - file { "interface-${name}": - ensure => $ensure, - path => "/etc/network/interfaces.d/${name}", - content => template($template), - notify => $network_notify, + } + # Configuration + if $use_netplan { + if $ipv4_address { + if $ipv4_netmask { + # TODO Handle ipv6 and multiple addresses + $ipv4_cidr = netmask2cidr($ipv4_netmask) + $addressv4 = [ "${ipv4_address}/${ipv4_cidr}" ] + } else { + fail('A ipv4_netmask must be set if ipv4_address is present') } - if ! defined(File_line['config_file_per_interface']) { - file_line { 'config_file_per_interface': - ensure => $ensure, - path => '/etc/network/ifupdown2/ifupdown2.conf', - line => 'addon_scripts_support=1', - match => 'addon_scripts_suppor*', - notify => $network_notify, + } else { + $addressv4 = undef + } + network::netplan::interface { $interface: + dhcp4 => $ipv4_dhcp, + dhcp6 => $ipv6_dhcp, + addresses => $addressv4, + gateway4 => $ipv4_gateway, + gateway6 => $ipv6_gateway, + } + } else { + if $::network::config_file_per_interface { + # Scenario with a file per interface + if ! defined(File['/etc/network/interfaces.d']) { + file { '/etc/network/interfaces.d': + ensure => 'directory', + mode => '0755', + owner => 'root', + group => 'root', } } - } else { - file { "interface-${name}": + file { $config_file_path: ensure => $ensure, - path => "/etc/network/interfaces.d/${name}.cfg", - content => template($template), - notify => $network_notify, + content => $content, + notify => $real_config_file_notify, } if ! defined(File_line['config_file_per_interface']) { file_line { 'config_file_per_interface': ensure => $ensure, path => '/etc/network/interfaces', line => 'source /etc/network/interfaces.d/*.cfg', - notify => $network_notify, + notify => $real_config_file_notify, } } - } - File['/etc/network/interfaces.d'] - -> File["interface-${name}"] - } else { - if ! defined(Concat['/etc/network/interfaces']) { - concat { '/etc/network/interfaces': - mode => '0644', - owner => 'root', - group => 'root', - notify => $network_notify, + } else { + # Scenario with everything configured in /etc/network/interfaces + if ! defined(Concat['/etc/network/interfaces']) { + concat { '/etc/network/interfaces': + mode => '0644', + owner => 'root', + group => 'root', + notify => $real_config_file_notify, + } + } + concat::fragment { "interface-${title}": + target => '/etc/network/interfaces', + content => $content, + # order => pick($options['order'], 50), } - } - - concat::fragment { "interface-${name}": - target => '/etc/network/interfaces', - content => template($template), - order => $manage_order, - } - - } - if ! defined(Network::Interface['lo']) { - network::interface { 'lo': - address => '127.0.0.1', - method => 'loopback', - manage_order => '05', + if ! defined(Network::Interface['lo']) { + network::interface { 'lo': + address => '127.0.0.1', + method => 'loopback', + options => { 'order' => '05' }, + } + } } } } - 'RedHat': { - file { "/etc/sysconfig/network-scripts/ifcfg-${name}": + # On Cumulus we manage "/etc/network/interfaces.d/${name}" + # and line addon_scripts_support=1 in /etc/network/ifupdown2/ifupdown2.conf + 'CumulusLinux': { + # Configuration + file { $config_file_path: ensure => $ensure, - content => template($template), - mode => '0644', - owner => 'root', - group => 'root', - notify => $network_notify, + content => $content, + notify => $real_config_file_notify, } - } - - 'Suse': { - if $vlan { - if !defined(Package['vlan']) { - package { 'vlan': - ensure => 'present', - } + if ! defined(File_line['config_file_per_interface']) { + file_line { 'config_file_per_interface': + ensure => $ensure, + path => '/etc/network/ifupdown2/ifupdown2.conf', + line => 'addon_scripts_support=1', + match => 'addon_scripts_suppor*', + notify => $real_config_file_notify, } - Package['vlan'] - -> File["/etc/sysconfig/network/ifcfg-${name}"] - } - if $bridge { - if !defined(Package['bridge-utils']) { - package { 'bridge-utils': - ensure => 'present', - } - } - Package['bridge-utils'] - -> File["/etc/sysconfig/network/ifcfg-${name}"] - } - - file { "/etc/sysconfig/network/ifcfg-${name}": - ensure => $ensure, - content => template($template), - mode => '0600', - owner => 'root', - group => 'root', - notify => $network_notify, } } + # On Solaris we manage "/etc/hostname.${title}" + # ipadm exec, host entry and network service 'Solaris': { + # Configuration if $::operatingsystemrelease == '5.11' { if ! defined(Service['svc:/network/physical:nwam']) { service { 'svc:/network/physical:nwam': ensure => stopped, enable => false, - before => [ - Service['svc:/network/physical:default'], - Exec["create ipaddr ${title}"], - File["hostname iface ${title}"], - ], } } + Service['svc:/network/physical:nwam'] + -> Service['svc:/network/physical:default'] + -> Exec["create ipaddr ${title}"] + -> File[$config_file_path] } case $::operatingsystemmajrelease { '11','5': { if $enable_dhcp { - $create_ip_command = "ipadm create-addr -T dhcp ${title}/dhcp" - $show_ip_command = "ipadm show-addr ${title}/dhcp" + $create_ip_command = "ipadm create-addr -T dhcp ${interface}/dhcp" + $show_ip_command = "ipadm show-addr ${interface}/dhcp" } else { - $create_ip_command = "ipadm create-addr -T static -a ${ipaddress}/${netmask} ${title}/v4static" - $show_ip_command = "ipadm show-addr ${title}/v4static" + $create_ip_command = "ipadm create-addr -T static -a ${ipv4_address}/${ipv4_netmask} ${interface}/v4static" + $show_ip_command = "ipadm show-addr ${interface}/v4static" } } default: { @@ -811,37 +470,34 @@ command => $create_ip_command, unless => $show_ip_command, path => '/bin:/sbin:/usr/sbin:/usr/bin:/usr/gnu/bin', - tag => 'solaris', } - file { "hostname iface ${title}": - ensure => file, - path => "/etc/hostname.${title}", - content => inline_template("<%= @ipaddress %> netmask <%= @netmask %>\n"), + file { $config_file_path: + ensure => $ensure, + content => $content, require => Exec["create ipaddr ${title}"], - tag => 'solaris', } host { $::fqdn: ensure => present, - ip => $ipaddress, + ip => $ipv4_address, host_aliases => [$::hostname], - require => File["hostname iface ${title}"], + require => File[$config_file_path], } if ! defined(Service['svc:/network/physical:default']) { service { 'svc:/network/physical:default': - ensure => running, - enable => true, - subscribe => [ - File["hostname iface ${title}"], - Exec["create ipaddr ${title}"], - ], + ensure => running, + enable => true, } } + Service['svc:/network/physical:default'] ~> File[$config_file_path] + Service['svc:/network/physical:default'] ~> Exec["create ipaddr ${interface}"] } + # Other OS not supported default: { - alert("${::operatingsystem} not supported. No changes done here.") + if ! $suppress_warnings { + alert("${::operatingsystem} not supported. Nothing done here. Set \$suppress_warnings to true to disable this message") + } } - } } diff --git a/manifests/legacy/interface.pp b/manifests/legacy/interface.pp new file mode 100644 index 0000000..d089a79 --- /dev/null +++ b/manifests/legacy/interface.pp @@ -0,0 +1,847 @@ +# +# = Define: network::legacy::interface +# +# This define manages interfaces. +# Currently only Debian and RedHat families supported. +# Some parameters are supported only for specific families +# +# == Common parameters +# +# $enable_dhcp +# Boolean. Default: false +# Activates DHCP on the interface +# +# [*ipaddress*] +# [*netmask*] +# [*broadcast*] +# [*hwaddr*] +# String. Default: undef +# Standard network parameters +# +# [*enable*] +# Boolean. Default: true +# Manages the interface presence. Possible values: +# * true - Interface created and enabled at boot. +# * false - Interface removed from boot. +# +# [*template*] +# String. Optional. Default: Managed by module. +# Provide an alternative custom template to use for configuration of: +# - On Debian: file fragments in /etc/network/interfaces +# - On RedHat: files /etc/sysconfig/network-scripts/ifcfg-${name} +# You can copy and adapt network/templates/interface/${::osfamily}.erb +# +# [*restart_all_nic*] +# Boolean. Default: true +# Manages the way to apply interface creation/modification: +# - If true, will trigger a restart of all network interfaces +# - If false, will only start/restart this specific interface +# +# [*reload_command*] +# String. Default: $::operatingsystem ? {'CumulusLinux' => 'ifreload -a', +# default => "ifdown ${interface}; ifup ${interface}", +# } +# Defines the command(s) that will be used to reload a nic when restart_all_nic +# is set to false +# +# [*options*] +# A generic hash of custom options that can be used in a custom template +# +# [*options_extra_redhat*] +# [*options_extra_debian*] +# [*options_extra_suse*] +# Custom hashes of options that are added to the default template that manages +# interfaces respectively under RedHat, Debian and Suse families +# +# [*description*] +# String. Optional. Default: undef +# Adds comment with given description in file before interface declaration. +# +# == Debian only parameters +# +# $address = undef, +# Both ipaddress (standard name) and address (Debian param name) if set +# configure the ipv4 address of the interface. +# If both are present address is used. +# Note, that if $my_inner_ipaddr (for GRE) is set - it is used instead. +# +# $manage_order = 10, +# This is used by concat to define the order of your fragments, +# can be used to load an interface before another. +# default it's 10. +# +# $method = '', +# Both enable_dhcp (standard) and method (Debian specific param name) if set +# configure dhcp on the interface via the method setting. +# If both are present method is used. +# +# $up = [ ], +# $pre_up = [ ], +# $post_up = [ ], +# $down = [ ], +# $pre_down = [ ], +# $post_down = [ ], +# Map to Debian interfaces parameters (with _ instead of -) +# Note that these params MUST be arrays, even if with only one element +# +# $nonlocal_gateway = undef, +# Gateway, that does not belong to interface's network and needs extra +# route to be available. Shortcut for: +# +# post-up ip route add $nonlocal_gateway dev $interface +# post-up ip route add default via $nonlocal_gateway dev $interface +# pre-down ip route del default via $nonlocal_gateway dev $interface +# pre-down ip route del $nonlocal_gateway dev $interface +# +# $additional_networks = [], +# Convenience shortcut to add more networks to the interface. Expands to: +# +# up ip addr add $network dev $interface +# down ip addr del $network dev $interface +# +# Check the arguments in the code for the other Debian specific settings +# If defined they are set in the used template. +# +# == RedHat only parameters +# +# $type = 'Ethernet', +# Defaults to 'Ethernet', but following types are supported for OVS: +# "OVSPort", "OVSIntPort", "OVSBond", "OVSTunnel" and "OVSPatchPort". +# 'InfiniBand' type is supported as well. +# +# $ipaddr = undef, +# Both ipaddress (standard name) and ipaddr (RedHat param name) if set +# configure the ipv4 address of the interface. +# If both are present ipaddr is used. +# +# $hwaddr = undef, +# hwaddr if set configures the mac address of the interface. +# +# $prefix = undef, +# Network PREFIX aka CIDR notation of the network mask. The PREFIX +# takes precedence if both PREFIX and NETMASK are set. +# +# $bootproto = '', +# Both enable_dhcp (standard) and bootproto (Debian specific param name), +# if set, configure dhcp on the interface via the bootproto setting. +# If both are present bootproto is used. +# +# $arpcheck = undef +# Whether the interface will check if the supplied IP address is already in +# use. Valid values are undef, "yes", "no". +# +# $arp = undef +# Used to enable or disable ARP completely for an interface at initialization +# Valid values are undef, "yes", "no". +# +# $nozeroconf = undef +# Used to enable or disable ZEROCONF routes completely for an +# interface at initialization +# Valid values are undef, "yes, 'no". +# +# $linkdelay = undef +# Used to introduce a delay (sleep) of the specified number of seconds when +# bringing an interface up. +# +# $check_link_down = false +# Set to true to add check_link_down function in the interface file +# +# $hotswap = undef +# Set to no to prevent interface from being activated when hot swapped - Default is yes +# +# $vid = undef +# Set to specify vlan id # +# +# == RedHat and Debian only GRE interface specific parameters +# +# $peer_outer_ipaddr = undef +# IP address of the remote tunnel endpoint +# +# $peer_inner_ipaddr = undef +# IP address of the remote end of the tunnel interface. If this is specified, +# a route to PEER_INNER_IPADDR through the tunnel is added automatically. +# +# $my_outer_ipaddr = undef +# IP address of the local tunnel endpoint. If unspecified, an IP address +# is selected automatically for outgoing tunnel packets, and incoming tunnel +# packets are accepted on all local IP addresses. +# +# $my_inner_ipaddr = undef +# Local IP address of the tunnel interface. +# +# == RedHat only Open vSwitch specific parameters +# +# $devicetype = undef, +# Always set to "ovs" if configuring OVS* type. +# +# $bond_ifaces = undef, +# Physical interfaces for "OVSBond". +# +# $ovs_bridge = undef, +# For types other than "OVSBridge" type. It specifies the OVS bridge +# to which port, patch or tunnel should be attached to. +# +# $ovs_ports = undef, +# It specifies the OVS ports should OVS bridge attach +# +# $ovs_extra = undef, +# Optional: extra ovs-vsctl commands seperate by "--" (double dash) +# +# $ovs_options = undef, +# Optional: extra options to set in the Port table. +# Check ovs-vsctl's add-port man page. +# +# $ovs_patch_peer = undef, +# Patche's peer on the other bridge for "OVSPatchPort" type. +# +# $ovs_tunnel_type = undef, +# Tunnel types (eg. "vxlan", "gre") for "OVSTunnel" type. +# +# $ovs_tunnel_options = undef, +# Tunnel options (eg. "remote_ip") for "OVSTunnel" type. +# +# $ovsdhcpinterfaces = undef, +# All the interfaces that can reach the DHCP server as a space separated list +# +# $ovsbootproto = undef, +# Needs OVSBOOTPROTO instead of BOOTPROTO to enable DHCP on the bridge +# +# Check the arguments in the code for the other RedHat specific settings +# If defined they are set in the used template. +# +# == RedHat only InfiniBand specific parameters +# +# $connected_mode = undef, +# Enable or not InfiniBand CONNECTED_MODE. It true, CONNECTED_MODE=yes will +# be added to ifcfg file. +# +# == Suse and Debian only parameters +# +# $aliases = undef +# Array of aliased IPs for given interface. +# Note, that for Debian generated interfaces will have static method and +# netmask 255.255.255.255. If you need something other - generate +# interfaces by hand. Also note, that interfaces will be named +# $interface:$idx, where $idx is IP index in list, starting from 0. +# If you're adding manual interfaces - beware of clashes. +# +# == Suse only parameters +# +# Check the arguments in the code for the other Suse specific settings +# If defined they are set in the used template. +# +# +# == Red Hat zLinux on IBM ZVM/System Z (s390/s390x) only parameters +# +# $subchannels = undef, +# The hardware addresses of QETH or Hipersocket hardware. +# +# $nettype = undef, +# The networking hardware type. qeth, lcs or ctc. +# The default is 'qeth'. +# +# $layer2 = undef, +# The networking layer mode in Red Hat 6. 0 or 1. +# The defauly is 0. From Red Hat 7 this is confifured using the options +# parameter below. +# +# $zlinux_options = undef +# You can add any valid sysfs attribute and its value to the OPTIONS +# parameter.The Red Hat Enterprise Linux (7 )installation program currently +# uses this to configure the layer mode (layer2) and the relative port +# number (portno) of qeth devices. +define network::legacy::interface ( + + $enable = true, + $ensure = 'present', + $template = "network/legacy/interface/${::osfamily}.erb", + $options = undef, + $options_extra_redhat = undef, + $options_extra_debian = undef, + $options_extra_suse = undef, + $interface = $name, + $restart_all_nic = true, + $reload_command = undef, + + $enable_dhcp = false, + + $ipaddress = '', + $netmask = undef, + $network = undef, + $broadcast = undef, + $gateway = undef, + $hwaddr = undef, + $mtu = undef, + + $description = undef, + + ## Debian specific + $manage_order = '10', + $auto = true, + $allow_hotplug = undef, + $method = '', + $family = 'inet', + $stanza = 'iface', + $address = '', + $dns_search = undef, + $dns_nameservers = undef, + # For method: static + $metric = undef, + $pointopoint = undef, + + # For method: dhcp + $hostname = undef, + $leasehours = undef, + $leasetime = undef, + $client = undef, + + # For method: bootp + $bootfile = undef, + $server = undef, + + # For method: tunnel + $mode = undef, + $endpoint = undef, + $dstaddr = undef, + $local = undef, + $ttl = undef, + + # For method: ppp + $provider = undef, + $unit = undef, + + # For inet6 family + $privext = undef, + $dhcp = undef, + $media = undef, + $accept_ra = undef, + $autoconf = undef, + $vlan_raw_device = undef, + + # Convenience shortcuts + $nonlocal_gateway = undef, + $additional_networks = [ ], + + # Common ifupdown scripts + $up = [ ], + $pre_up = [ ], + $post_up = [ ], + $down = [ ], + $pre_down = [ ], + $post_down = [ ], + + # For virtual routing and forwarding (VRF) + $vrf = undef, + $vrf_table = undef, + + # For bonding + $slaves = [ ], + $bond_mode = undef, + $bond_miimon = undef, + $bond_downdelay = undef, + $bond_updelay = undef, + $bond_lacp_rate = undef, + $bond_master = undef, + $bond_primary = undef, + $bond_slaves = [ ], + $bond_xmit_hash_policy = undef, + $bond_num_grat_arp = undef, + $bond_arp_all = undef, + $bond_arp_interval = undef, + $bond_arp_iptarget = undef, + $bond_fail_over_mac = undef, + $bond_ad_select = undef, + $use_carrier = undef, + $primary_reselect = undef, + + # For teaming + $team_config = undef, + $team_port_config = undef, + $team_master = undef, + + # For bridging + $bridge_ports = [ ], + $bridge_stp = undef, + $bridge_fd = undef, + $bridge_maxwait = undef, + $bridge_waitport = undef, + + # For wpa_supplicant + $wpa_ssid = undef, + $wpa_bssid = undef, + $wpa_psk = undef, + $wpa_key_mgmt = [ ], + $wpa_group = [ ], + $wpa_pairwise = [ ], + $wpa_auth_alg = [ ], + $wpa_proto = [ ], + $wpa_identity = undef, + $wpa_password = undef, + $wpa_scan_ssid = undef, + $wpa_ap_scan = undef, + + ## RedHat specific + $ipaddr = '', + $prefix = undef, + $uuid = undef, + $bootproto = '', + $userctl = 'no', + $type = 'Ethernet', + $ethtool_opts = undef, + $ipv6init = undef, + $ipv6_autoconf = undef, + $ipv6_privacy = undef, + $ipv6_addr_gen_mode = undef, + $ipv6addr = undef, + $ipv6addr_secondaries = [], + $ipv6_defaultgw = undef, + $dhcp_hostname = undef, + $srcaddr = undef, + $peerdns = '', + $peerntp = '', + $onboot = '', + $onparent = undef, + $defroute = undef, + $dns1 = undef, + $dns2 = undef, + $dns3 = undef, + $domain = undef, + $nm_controlled = undef, + $master = undef, + $slave = undef, + $bonding_master = undef, + $bonding_opts = undef, + $vlan = undef, + $vlan_name_type = undef, + $vlan_id = undef, + $vid = undef, + $physdev = undef, + $bridge = undef, + $arpcheck = undef, + $zone = undef, + $arp = undef, + $nozeroconf = undef, + $linkdelay = undef, + $check_link_down = false, + $hotplug = undef, + $persistent_dhclient = undef, + $nm_name = undef, + + # RedHat specific for InfiniBand + $connected_mode = undef, + + # RedHat specific for GRE + $peer_outer_ipaddr = undef, + $peer_inner_ipaddr = undef, + $my_outer_ipaddr = undef, + $my_inner_ipaddr = undef, + + # RedHat and Debian specific for Open vSwitch + $devicetype = undef, # On RedHat. Same of ovs_type for Debian + $bond_ifaces = undef, # On RedHat Same of ovs_bonds for Debian + $ovs_type = undef, # Debian + $ovs_bonds = undef, # Debian + $ovs_bridge = undef, + $ovs_ports = undef, + $ovs_extra = undef, + $ovs_options = undef, + $ovs_patch_peer = undef, + $ovsrequires = undef, + $ovs_tunnel_type = undef, + $ovs_tunnel_options = undef, + $ovsdhcpinterfaces = undef, + $ovsbootproto = undef, + + # RedHat specific for zLinux + $subchannels = undef, + $nettype = undef, + $layer2 = undef, + $zlinux_options = undef, + + ## Suse specific + $startmode = '', + $usercontrol = 'no', + $firewall = undef, + $aliases = undef, + $remote_ipaddr = undef, + $check_duplicate_ip = undef, + $send_gratuitous_arp = undef, + $pre_up_script = undef, + $post_up_script = undef, + $pre_down_script = undef, + $post_down_script = undef, + + # For bonding + $bond_moduleopts = undef, + # also used for Suse bonding: $bond_master, $bond_slaves + + # For bridging + $bridge_fwddelay = undef, + # also used for Suse bridging: $bridge, $bridge_ports, $bridge_stp + + # For vlan + $etherdevice = undef, + # also used for Suse vlan: $vlan + + ) { + + include ::network + + validate_bool($auto) + validate_bool($enable) + validate_bool($restart_all_nic) + + validate_array($up) + validate_array($pre_up) + validate_array($down) + validate_array($pre_down) + validate_array($slaves) + validate_array($bond_slaves) + validate_array($bridge_ports) + validate_array($wpa_key_mgmt) + validate_array($wpa_group) + validate_array($wpa_pairwise) + validate_array($wpa_auth_alg) + validate_array($wpa_proto) + + # $subchannels is only valid for zLinux/SystemZ/s390x. + if $::architecture == 's390x' { + validate_array($subchannels) + validate_re($nettype, '^(qeth|lcs|ctc)$', "${name}::\$nettype may be 'qeth', 'lcs' or 'ctc' only and is set to <${nettype}>.") + # Different parameters required for RHEL6 and RHEL7 + if $::operatingsystemmajrelease =~ /^7/ { + validate_string($zlinux_options) + } else { + validate_re($layer2, '^0|1$', "${name}::\$layer2 must be 1 or 0 and is to <${layer2}>.") + } + } + + if $arp != undef and ! ($arp in ['yes', 'no']) { + fail('arp must be one of: undef, yes, no') + } + + if $arpcheck != undef and ! ($arpcheck in ['yes', 'no']) { + fail('arpcheck must be one of: undef, yes, no') + } + + if $nozeroconf != undef and ! ($nozeroconf in ['yes', 'no']) { + fail('nozeroconf must be one of: undef, yes, no') + } + + if $check_duplicate_ip != undef and ! ($check_duplicate_ip in ['yes', 'no']) { + fail('check_duplicate_ip must be one of: undef, yes, no') + } + + if $send_gratuitous_arp != undef and ! ($send_gratuitous_arp in ['yes', 'no']) { + fail('send_gratuitous_arp must be one of: undef, yes, no') + } + + if $::osfamily != 'RedHat' and ($type == 'InfiniBand' or $connected_mode) { + fail('InfiniBand parameters are supported only for RedHat family.') + } + + if $type != 'InfiniBand' and $connected_mode != undef { + fail('CONNECTED_MODE parameter available for InfiniBand interfaces only') + } + + if $prefix != undef and $netmask != undef { + fail('Use either netmask or prefix to define the netmask for the interface') + } + + $manage_hwaddr = $hwaddr ? { + default => $hwaddr, + } + + $manage_method = $method ? { + '' => $enable_dhcp ? { + true => 'dhcp', + false => 'static', + }, + default => $method, + } + + # Debian specific + case $manage_method { + 'auto': { $manage_address = undef } + 'bootp': { $manage_address = undef } + 'dhcp': { $manage_address = undef } + 'ipv4ll': { $manage_address = undef } + 'loopback': { $manage_address = undef } + 'manual': { $manage_address = undef } + 'none': { $manage_address = undef } + 'ppp': { $manage_address = undef } + 'wvdial': { $manage_address = undef } + default: { + $manage_address = $my_inner_ipaddr ? { + undef => $address ? { + '' => $ipaddress, + default => $address, + }, + default => $my_inner_ipaddr, + } + } + } + + # Redhat and Suse specific + if $::operatingsystem == 'SLES' and versioncmp($::operatingsystemrelease, 12) >= 0 { + $bootproto_false = 'static' + } else { + $bootproto_false = 'none' + } + + $manage_bootproto = $bootproto ? { + '' => $enable_dhcp ? { + true => 'dhcp', + false => $bootproto_false + }, + default => $bootproto, + } + $manage_peerdns = $peerdns ? { + '' => $manage_bootproto ? { + 'dhcp' => 'yes', + default => 'no', + }, + true => 'yes', + false => 'no', + default => $peerdns, + } + $manage_peerntp = $peerntp ? { + '' => $manage_bootproto ? { + 'dhcp' => 'yes', + default => 'no', + }, + default => $peerntp, + } + $manage_ipaddr = $ipaddr ? { + '' => $ipaddress, + default => $ipaddr, + } + $manage_onboot = $onboot ? { + '' => $enable ? { + true => 'yes', + false => 'no', + }, + default => $onboot, + } + $manage_defroute = $defroute ? { + true => 'yes', + false => 'no', + default => $defroute, + } + $manage_startmode = $startmode ? { + '' => $enable ? { + true => 'auto', + false => 'off', + }, + default => $startmode, + } + + # Resources + $real_reload_command = $reload_command ? { + undef => $::operatingsystem ? { + 'CumulusLinux' => 'ifreload -a', + default => "ifdown ${interface} --force ; ifup ${interface}", + }, + default => $reload_command, + } + if $restart_all_nic == false and $::kernel == 'Linux' { + exec { "network_restart_${name}": + command => $real_reload_command, + path => '/sbin', + refreshonly => true, + } + $network_notify = "Exec[network_restart_${name}]" + } else { + $network_notify = $network::manage_config_file_notify + } + + case $::osfamily { + + 'Debian': { + if $vlan_raw_device { + if versioncmp('9.0', $::operatingsystemrelease) >= 0 + and !defined(Package['vlan']) { + package { 'vlan': + ensure => 'present', + } + } + } + + if $network::config_file_per_interface { + if ! defined(File['/etc/network/interfaces.d']) { + file { '/etc/network/interfaces.d': + ensure => 'directory', + mode => '0755', + owner => 'root', + group => 'root', + } + } + if $::operatingsystem == 'CumulusLinux' { + file { "interface-${name}": + ensure => $ensure, + path => "/etc/network/interfaces.d/${name}", + content => template($template), + notify => $network_notify, + } + if ! defined(File_line['config_file_per_interface']) { + file_line { 'config_file_per_interface': + ensure => $ensure, + path => '/etc/network/ifupdown2/ifupdown2.conf', + line => 'addon_scripts_support=1', + match => 'addon_scripts_suppor*', + notify => $network_notify, + } + } + } else { + file { "interface-${name}": + ensure => $ensure, + path => "/etc/network/interfaces.d/${name}.cfg", + content => template($template), + notify => $network_notify, + } + if ! defined(File_line['config_file_per_interface']) { + file_line { 'config_file_per_interface': + ensure => $ensure, + path => '/etc/network/interfaces', + line => 'source /etc/network/interfaces.d/*.cfg', + notify => $network_notify, + } + } + } + File['/etc/network/interfaces.d'] + -> File["interface-${name}"] + } else { + if ! defined(Concat['/etc/network/interfaces']) { + concat { '/etc/network/interfaces': + mode => '0644', + owner => 'root', + group => 'root', + notify => $network_notify, + } + } + + concat::fragment { "interface-${name}": + target => '/etc/network/interfaces', + content => template($template), + order => $manage_order, + } + + } + + if ! defined(Network::Legacy::Interface['lo']) { + network::legacy::interface { 'lo': + address => '127.0.0.1', + method => 'loopback', + manage_order => '05', + } + } + } + + 'RedHat': { + file { "/etc/sysconfig/network-scripts/ifcfg-${name}": + ensure => $ensure, + content => template($template), + mode => '0644', + owner => 'root', + group => 'root', + notify => $network_notify, + } + } + + 'Suse': { + if $vlan { + if !defined(Package['vlan']) { + package { 'vlan': + ensure => 'present', + } + } + Package['vlan'] + -> File["/etc/sysconfig/network/ifcfg-${name}"] + } + if $bridge { + if !defined(Package['bridge-utils']) { + package { 'bridge-utils': + ensure => 'present', + } + } + Package['bridge-utils'] + -> File["/etc/sysconfig/network/ifcfg-${name}"] + } + + file { "/etc/sysconfig/network/ifcfg-${name}": + ensure => $ensure, + content => template($template), + mode => '0600', + owner => 'root', + group => 'root', + notify => $network_notify, + } + } + + 'Solaris': { + if $::operatingsystemrelease == '5.11' { + if ! defined(Service['svc:/network/physical:nwam']) { + service { 'svc:/network/physical:nwam': + ensure => stopped, + enable => false, + before => [ + Service['svc:/network/physical:default'], + Exec["create ipaddr ${title}"], + File["hostname iface ${title}"], + ], + } + } + } + case $::operatingsystemmajrelease { + '11','5': { + if $enable_dhcp { + $create_ip_command = "ipadm create-addr -T dhcp ${title}/dhcp" + $show_ip_command = "ipadm show-addr ${title}/dhcp" + } else { + $create_ip_command = "ipadm create-addr -T static -a ${ipaddress}/${netmask} ${title}/v4static" + $show_ip_command = "ipadm show-addr ${title}/v4static" + } + } + default: { + $create_ip_command = 'true ' + $show_ip_command = 'true ' + } + } + exec { "create ipaddr ${title}": + command => $create_ip_command, + unless => $show_ip_command, + path => '/bin:/sbin:/usr/sbin:/usr/bin:/usr/gnu/bin', + tag => 'solaris', + } + file { "hostname iface ${title}": + ensure => file, + path => "/etc/hostname.${title}", + content => inline_template("<%= @ipaddress %> netmask <%= @netmask %>\n"), + require => Exec["create ipaddr ${title}"], + tag => 'solaris', + } + host { $::fqdn: + ensure => present, + ip => $ipaddress, + host_aliases => [$::hostname], + require => File["hostname iface ${title}"], + } + if ! defined(Service['svc:/network/physical:default']) { + service { 'svc:/network/physical:default': + ensure => running, + enable => true, + subscribe => [ + File["hostname iface ${title}"], + Exec["create ipaddr ${title}"], + ], + } + } + } + + default: { + alert("${::operatingsystem} not supported. No changes done here.") + } + + } + +} diff --git a/manifests/mroute.pp b/manifests/legacy/mroute.pp similarity index 92% rename from manifests/mroute.pp rename to manifests/legacy/mroute.pp index d31742b..3347647 100644 --- a/manifests/mroute.pp +++ b/manifests/legacy/mroute.pp @@ -1,4 +1,4 @@ -# == Definition: network::mroute +# == Definition: network::legacy::mroute # # Manages multiples routes on a single file # Configures /etc/sysconfig/networking-scripts/route-$name on Rhel @@ -53,7 +53,7 @@ # On Suse # Deploys the file /etc/sysconfig/network/ifroute-$name. # -define network::mroute ( +define network::legacy::mroute ( $routes, $interface = $name, $config_file_notify = 'class_default', @@ -73,15 +73,15 @@ $real_route_up_template = $route_up_template ? { undef => $::osfamily ? { - 'RedHat' => 'network/mroute-RedHat.erb', - 'Debian' => 'network/mroute_up-Debian.erb', - 'SuSE' => 'network/mroute-SuSE.erb', + 'RedHat' => 'network/legacy/mroute-RedHat.erb', + 'Debian' => 'network/legacy/mroute_up-Debian.erb', + 'SuSE' => 'network/legacy/mroute-SuSE.erb', }, default => $route_up_template, } $real_route_down_template = $route_down_template ? { undef => $::osfamily ? { - 'Debian' => 'network/mroute_down-Debian.erb', + 'Debian' => 'network/legacy/mroute_down-Debian.erb', default => undef, }, default => $route_down_template, diff --git a/manifests/params.pp b/manifests/legacy/params.pp similarity index 94% rename from manifests/params.pp rename to manifests/legacy/params.pp index 40594ed..73a4d81 100644 --- a/manifests/params.pp +++ b/manifests/legacy/params.pp @@ -1,8 +1,8 @@ -# Class: network::params +# Class: network::legacy::params # # Defines all the variables used in the module. # -class network::params { +class network::legacy::params { $service_restart_exec = $::osfamily ? { 'Debian' => '/sbin/ifdown -a --force ; /sbin/ifup -a', diff --git a/manifests/legacy/route.pp b/manifests/legacy/route.pp new file mode 100644 index 0000000..4cdcfdc --- /dev/null +++ b/manifests/legacy/route.pp @@ -0,0 +1,214 @@ +# == Definition: network::legacy::route +# +# Based on https://github.com/razorsedge/puppet-network/ route.pp manifest. +# Configures /etc/sysconfig/networking-scripts/route-$name on Rhel +# Adds 2 files on Debian: +# One under /etc/network/if-up.d and +# One in /etc/network/if-down.d +# +# === Parameters: +# +# $ipaddress - required +# $netmask - required +# $gateway - optional +# $metric - optional +# $mtu - optional +# $scope - optional +# $source - optional +# $table - optional +# $cidr - optional +# +# [*config_file_notify*] +# String. Optional. Default: 'class_default' +# Defines the notify argument of the created file. +# The default special value implies the same behaviour of the main class +# configuration file. Set to undef to remove any notify, or set +# the name(s) of the resources to notify +# +# +# === Actions: +# +# On Rhel +# Deploys 2 files under/etc/sysconfig/network-scripts/, route-$name and route6-$name +# +# On Debian +# Deploy 2 files 1 under /etc/network/if-up.d and 1 in /etc/network/if-down.d +# +# === Sample Usage: +# +# network::route { 'eth0': +# ipaddress => [ '192.168.17.0', ], +# netmask => [ '255.255.255.0', ], +# gateway => [ '192.168.17.250', ], +# } +# +# network::route { 'bond2': +# ipaddress => [ '192.168.2.0', '10.0.0.0', '::', ], +# netmask => [ '255.255.255.0', '255.0.0.0', '0', ], +# gateway => [ '192.168.1.1', '10.0.0.1', 'fd00::1', ], +# family => [ 'inet4', 'inet4', 'inet6', ], +# } +# +# Note that for the familiy parameter, everything else than "inet6" will be written +# as an IPv4 route. +# +# A routing table can also be specified for the route: +# +# network::route { 'eth1': +# ipaddress => [ '192.168.3.0', ], +# netmask => [ '255.255.255.0', ], +# gateway => [ '192.168.3.1', ], +# table => [ 'vlan22' ], +# } +# +# If adding routes to a routing table on an interface with multiple routes, it +# is necessary to specify false or 'main' for the table on the other routes. +# The 'main' routing table is where routes are added by default. +# +# The same applies if adding scope, source or gateway, i.e. false needs to be +# specified for those routes without values for those parameters, if defining +# multiple routes for the same interface. +# +# The first two routes in the following example are functionally equivalent to +# the routes added in the example above for bond2. +# +# network::route { 'bond2': +# ipaddress => [ '192.168.2.0', '10.0.0.0', '0.0.0.0', '192.168.3.0' ] +# netmask => [ '255.255.255.0', '255.0.0.0', '0.0.0.0', '255.255.255.0' ], +# gateway => [ '192.168.1.1', '10.0.0.1', '192.168.3.1', false ], +# scope => [ false, false, false, 'link', ], +# source => [ false, false, false, '192.168.3.10', ], +# table => [ false, false, 'vlan22' 'vlan22', ], +# } +# +# The second two routes yield the following routes in table vlan22: +# +# # ip route show table vlan22 +# default via 192.168.3.1 dev bond2 +# 192.168.3.0/255.255.255.0 dev bond2 scope link src 192.168.3.10 +# +# Normally the link level routing (192.168.3.0/255.255.255.0) is added +# automatically by the kernel when an interface is brought up. When using routing +# rules and routing tables, this does not happen, so this route must be added +# manually. +# +# +# === Authors: +# +# Mike Arnold +# Riccardo Capecchi +# +# === Copyright: +# +# Copyright (C) 2011 Mike Arnold, unless otherwise noted. +# +define network::legacy::route ( + $ipaddress, + $netmask, + $gateway = undef, + $metric = undef, + $mtu = undef, + $scope = undef, + $source = undef, + $table = undef, + $cidr = undef, + $family = [ 'inet4' ], + $interface = $name, + $ensure = 'present' +) { + # Validate our arrays + validate_array($ipaddress) + validate_array($netmask) + + if $gateway { + validate_array($gateway) + } + + if $metric { + validate_array($metric) + } + + if $mtu { + validate_integer($mtu) + } + + if $scope { + validate_array($scope) + } + + if $source { + validate_array($source) + } + + if $table { + validate_array($table) + } + + if $cidr { + validate_array($cidr) + $_cidr = $cidr + } else { + $_cidr = build_cidr_array($netmask) + } + + if $family { + validate_array($family) + } + + include ::network + + case $::osfamily { + 'RedHat': { + file { "route-${name}": + ensure => $ensure, + mode => '0644', + owner => 'root', + group => 'root', + path => "/etc/sysconfig/network-scripts/route-${name}", + content => template('network/legacy/route-RedHat.erb'), + notify => $network::manage_config_file_notify, + } + file { "route6-${name}": + ensure => $ensure, + mode => '0644', + owner => 'root', + group => 'root', + path => "/etc/sysconfig/network-scripts/route6-${name}", + content => template('network/legacy/route6-RedHat.erb'), + notify => $network::manage_config_file_notify, + } + } + 'Suse': { + file { "ifroute-${name}": + ensure => $ensure, + mode => '0644', + owner => 'root', + group => 'root', + path => "/etc/sysconfig/network/ifroute-${name}", + content => template('network/legacy/route-Suse.erb'), + notify => $network::manage_config_file_notify, + } + } + 'Debian': { + file { "routeup-${name}": + ensure => $ensure, + mode => '0755', + owner => 'root', + group => 'root', + path => "/etc/network/if-up.d/z90-route-${name}", + content => template('network/legacy/route_up-Debian.erb'), + notify => $network::manage_config_file_notify, + } + file { "routedown-${name}": + ensure => $ensure, + mode => '0755', + owner => 'root', + group => 'root', + path => "/etc/network/if-down.d/z90-route-${name}", + content => template('network/legacy/route_down-Debian.erb'), + notify => $network::manage_config_file_notify, + } + } + default: { fail('Operating system not supported') } + } +} # define network::route diff --git a/manifests/legacy/routing_table.pp b/manifests/legacy/routing_table.pp new file mode 100644 index 0000000..d8d33d2 --- /dev/null +++ b/manifests/legacy/routing_table.pp @@ -0,0 +1,46 @@ +# == Definition: network::legacy::routing_table +# +# Configures /etc/iproute2/rt_tables +# +# === Parameters: +# +# $table_id - required +# +# === Actions: +# +# Adds routing table id and name to /etc/iproute2/rt_tables +# +# === Sample Usage: +# +# network::routing_table { 'vlan22': +# table_id => '200', +# } +# +# === Authors: +# +# Marcus Furlong +# + +define network::legacy::routing_table ( + $table_id, + $table = $name + ) { + + if ! defined(Concat['/etc/iproute2/rt_tables']) { + concat { '/etc/iproute2/rt_tables': + owner => 'root', + group => 'root', + mode => '0644', + } + + concat::fragment { 'rt_tables-base': + target => '/etc/iproute2/rt_tables', + source => 'puppet:///modules/network/legacy/rt_tables', + } + } + + concat::fragment { "rt_tables-${table}": + target => '/etc/iproute2/rt_tables', + content => "${table_id}\t${table}\n", + } +} # define network::routing_table diff --git a/manifests/legacy/rule.pp b/manifests/legacy/rule.pp new file mode 100644 index 0000000..b0cd402 --- /dev/null +++ b/manifests/legacy/rule.pp @@ -0,0 +1,97 @@ +# == Definition: network::legacy::rule +# +# Configures /etc/sysconfig/networking-scripts/rule-$name on RHEL +# +# === Parameters: +# +# $iprule - required +# +# === Actions: +# +# On RHEL +# Deploys /etc/sysconfig/networking-scripts/rule-$name and /etc/sysconfig/networking-scripts/rule6-$name +# +# On Debian +# Deploys 2 files, 1 under /etc/network/if-up.d and 1 in /etc/network/if-down.d +# +# === Sample Usage: +# +# network::rule { 'eth0': +# iprule => ['from 192.168.22.0/24 lookup vlan22', ], +# } +# +# === Authors: +# +# Marcus Furlong +# + +define network::legacy::rule ( + $iprule, + $interface = $name, + $family = undef, + $ensure = 'present' +) { + # Validate our arrays + validate_array($iprule) + + if $family { + validate_array($family) + } + + include ::network + + case $::osfamily { + 'RedHat': { + file { "rule-${interface}": + ensure => present, + owner => root, + group => root, + mode => '0644', + path => "/etc/sysconfig/network-scripts/rule-${interface}", + content => template('network/rule-RedHat.erb'), + notify => $network::manage_config_file_notify, + } + file { "rule6-${interface}": + ensure => present, + owner => root, + group => root, + mode => '0644', + path => "/etc/sysconfig/network-scripts/rule6-${interface}", + content => template('network/rule6-RedHat.erb'), + notify => $network::manage_config_file_notify, + } + } + 'Suse': { + file { "ifrule-${interface}": + ensure => present, + owner => root, + group => root, + mode => '0644', + path => "/etc/sysconfig/network/ifrule-${interface}", + content => template('network/rule-RedHat.erb'), + notify => $network::manage_config_file_notify, + } + } + 'Debian': { + file { "ruleup-${name}": + ensure => $ensure, + mode => '0755', + owner => 'root', + group => 'root', + path => "/etc/network/if-up.d/z90-rule-${name}", + content => template('network/rule_up-Debian.erb'), + notify => $network::manage_config_file_notify, + } + file { "ruledown-${name}": + ensure => $ensure, + mode => '0755', + owner => 'root', + group => 'root', + path => "/etc/network/if-down.d/z90-rule-${name}", + content => template('network/rule_down-Debian.erb'), + notify => $network::manage_config_file_notify, + } + } + default: { fail('Operating system not supported') } + } +} # define network::rule diff --git a/manifests/netplan.pp b/manifests/netplan.pp new file mode 100644 index 0000000..947eb1f --- /dev/null +++ b/manifests/netplan.pp @@ -0,0 +1,48 @@ +# Define network::netplan +# +# Define to manage a netplan configuration file +# +define network::netplan ( + String $config_file_name = "50-${title}.yaml", + Enum['present','absent'] $ensure = 'present', + String $renderer = 'networkd', + Numeric $version = 2, + + Stdlib::Absolutepath $config_dir_path = '/etc/netplan', + + Hash $ethernets = {}, + Hash $wifis = {}, + Hash $bridges = {}, + Hash $bonds = {}, + Hash $tunnels = {}, + Hash $vlans = {}, + + Optional[String] $file_content = undef, + Optional[String] $file_source = undef, + +) { + + $netplan_data = { + 'network' => { + 'version' => $version, + 'renderer' => $renderer, + 'ethernets' => $ethernets, + 'wifis' => $wifis, + 'bridges' => $bridges, + 'bonds' => $bonds, + 'tunnels' => $tunnels, + 'vlans' => $vlans, + } + } + + $real_file_content = $file_source ? { + undef => pick($file_content,to_yaml($netplan_data)), + default => undef, + } + + file { "${config_dir_path}/${config_file_name}": + ensure => $ensure, + content => $real_file_content, + source => $file_source, + } +} diff --git a/manifests/netplan/interface.pp b/manifests/netplan/interface.pp new file mode 100644 index 0000000..68b13b2 --- /dev/null +++ b/manifests/netplan/interface.pp @@ -0,0 +1,90 @@ +# Define network::netplan::interface +# +# Define to manage an interface via netplan +# +define network::netplan::interface ( + Enum['present','absent'] $ensure = 'present', + + String $interface_name = $title, + String $config_file_name = "50-${title}.yaml", + String $interface_type = 'ethernet', + Hash $interface_options = {}, + + Stdlib::Absolutepath $config_dir_path = '/etc/netplan', + Optional[String]$reload_command = 'netplan apply', + + String $renderer = 'networkd', + Numeric $version = 2, + + Network::NetplanDhcp $dhcp4 = false, + Network::NetplanDhcp $dhcp6 = false, + + Optional[Stdlib::MAC] $macaddress = getvar("networking.interfaces.${interface_name}.mac"), + Variant[Undef,Network::NetplanAddresses] $addresses = undef, + Variant[Undef,Array] $routes = undef, + Optional[Stdlib::Compat::Ipv4] $gateway4 = undef, + Optional[Stdlib::Compat::Ipv6] $gateway6 = undef, + Optional[Hash] $nameservers = undef, + Optional[Hash] $parameters = undef, + + Optional[String] $file_content = undef, + Optional[String] $file_source = undef, + +) { + + # Define how to restart network service + if $reload_command { + $network_notify = 'Exec[network::netplan::interface reload]' + if !defined(Exec['network::netplan::interface reload']) { + exec { 'network::netplan::interface reload': + command => $reload_command, + refreshonly => true, + path => $::path + } + } + pick_default($reload_command, $::network::manage_config_file_notify) + } else { + $network_notify = pick_default($::network::manage_config_file_notify) + } + + $match_values = $macaddress ? { + undef => {}, + default => { + match => { + macaddress => $macaddress, + } + } + } + + $default_values = { + dhcp4 => $dhcp4, + dhcp6 => $dhcp6, + addresses => $addresses, + gateway4 => $gateway4, + gateway6 => $gateway6, + routes => $routes, + nameservers => $nameservers, + parameters => $parameters, + } + + $netplan_data = { + 'network' => { + 'version' => $version, + "${interface_type}s" => { + $interface_name => delete_undef_values($default_values + $match_values + $interface_options), + } + } + } + + $real_file_content = $file_source ? { + undef => pick($file_content,to_yaml($netplan_data)), + default => undef, + } + file { "${config_dir_path}/${config_file_name}": + ensure => $ensure, + content => $real_file_content, + source => $file_source, + notify => $network_notify, + } + +} diff --git a/manifests/route.pp b/manifests/route.pp index 8f86ad3..6a2ad84 100644 --- a/manifests/route.pp +++ b/manifests/route.pp @@ -1,22 +1,40 @@ # == Definition: network::route # -# Based on https://github.com/razorsedge/puppet-network/ route.pp manifest. +# Manages multiples routes on a single file # Configures /etc/sysconfig/networking-scripts/route-$name on Rhel # Adds 2 files on Debian: # One under /etc/network/if-up.d and # One in /etc/network/if-down.d # +# Is based on the legacy network::mroute define of version 3 of this module. +# # === Parameters: # -# $ipaddress - required -# $netmask - required -# $gateway - optional -# $metric - optional -# $mtu - optional -# $scope - optional -# $source - optional -# $table - optional -# $cidr - optional +# [*routes*] +# Required parameter. Must be an hash of network-gateway pairs. +# Example: +# network::mroute { 'bond1': +# routes => { +# '99.99.228.0/24' => 'bond1', +# '100.100.244.0/22' => '174.136.107.1', +# } +# } +# +# ECMP route with two gateways example (works only with RedHat and Debian): +# +# network::mroute { 'bond1': +# routes => { +# '99.99.228.0/24' => 'bond1', +# '100.100.244.0/22' => ['174.136.107.1', '174.136.107.2'], +# } +# } +# +# [*route_up_template*] +# Template to use to manage route up setup. Default is defined according to +# $::osfamily +# +# [*route_down_template*] +# Template to use to manage route down script. Used only on Debian family. # # [*config_file_notify*] # String. Optional. Default: 'class_default' @@ -29,134 +47,55 @@ # === Actions: # # On Rhel -# Deploys 2 files under/etc/sysconfig/network-scripts/, route-$name and route6-$name +# Deploys the file /etc/sysconfig/network-scripts/route-$name. # # On Debian # Deploy 2 files 1 under /etc/network/if-up.d and 1 in /etc/network/if-down.d # -# === Sample Usage: -# -# network::route { 'eth0': -# ipaddress => [ '192.168.17.0', ], -# netmask => [ '255.255.255.0', ], -# gateway => [ '192.168.17.250', ], -# } -# -# network::route { 'bond2': -# ipaddress => [ '192.168.2.0', '10.0.0.0', '::', ], -# netmask => [ '255.255.255.0', '255.0.0.0', '0', ], -# gateway => [ '192.168.1.1', '10.0.0.1', 'fd00::1', ], -# family => [ 'inet4', 'inet4', 'inet6', ], -# } -# -# Note that for the familiy parameter, everything else than "inet6" will be written -# as an IPv4 route. -# -# A routing table can also be specified for the route: -# -# network::route { 'eth1': -# ipaddress => [ '192.168.3.0', ], -# netmask => [ '255.255.255.0', ], -# gateway => [ '192.168.3.1', ], -# table => [ 'vlan22' ], -# } -# -# If adding routes to a routing table on an interface with multiple routes, it -# is necessary to specify false or 'main' for the table on the other routes. -# The 'main' routing table is where routes are added by default. -# -# The same applies if adding scope, source or gateway, i.e. false needs to be -# specified for those routes without values for those parameters, if defining -# multiple routes for the same interface. -# -# The first two routes in the following example are functionally equivalent to -# the routes added in the example above for bond2. -# -# network::route { 'bond2': -# ipaddress => [ '192.168.2.0', '10.0.0.0', '0.0.0.0', '192.168.3.0' ] -# netmask => [ '255.255.255.0', '255.0.0.0', '0.0.0.0', '255.255.255.0' ], -# gateway => [ '192.168.1.1', '10.0.0.1', '192.168.3.1', false ], -# scope => [ false, false, false, 'link', ], -# source => [ false, false, false, '192.168.3.10', ], -# table => [ false, false, 'vlan22' 'vlan22', ], -# } -# -# The second two routes yield the following routes in table vlan22: -# -# # ip route show table vlan22 -# default via 192.168.3.1 dev bond2 -# 192.168.3.0/255.255.255.0 dev bond2 scope link src 192.168.3.10 -# -# Normally the link level routing (192.168.3.0/255.255.255.0) is added -# automatically by the kernel when an interface is brought up. When using routing -# rules and routing tables, this does not happen, so this route must be added -# manually. -# -# -# === Authors: -# -# Mike Arnold -# Riccardo Capecchi -# -# === Copyright: -# -# Copyright (C) 2011 Mike Arnold, unless otherwise noted. +# On Suse +# Deploys the file /etc/sysconfig/network/ifroute-$name. # define network::route ( - $ipaddress, - $netmask, - $gateway = undef, - $metric = undef, - $mtu = undef, - $scope = undef, - $source = undef, - $table = undef, - $cidr = undef, - $family = [ 'inet4' ], - $interface = $name, - $ensure = 'present' + Optional[Hash] $routes = {}, + Optional[Hash] $ipv6_routes = {}, + String $interface = $title, + Variant[Undef,Resource,String] $config_file_notify = 'class_default', + Enum['present','absent'] $ensure = 'present', + Enum['ipv4','ipv6'] $family = 'ipv4', + Optional[String] $route_up_template = undef, + Optional[String] $route_down_template = undef, ) { - # Validate our arrays - validate_array($ipaddress) - validate_array($netmask) - - if $gateway { - validate_array($gateway) - } - if $metric { - validate_array($metric) - } - - if $mtu { - validate_integer($mtu) - } - - if $scope { - validate_array($scope) - } + include ::network - if $source { - validate_array($source) + $real_config_file_notify = $config_file_notify ? { + 'class_default' => $::network::manage_config_file_notify, + default => $config_file_notify, } - if $table { - validate_array($table) + $real_route_up_template = $route_up_template ? { + undef => $::osfamily ? { + 'RedHat' => 'network/route-RedHat.erb', + 'Debian' => 'network/route_up-Debian.erb', + 'SuSE' => 'network/route-SuSE.erb', + }, + default => $route_up_template, } - - if $cidr { - validate_array($cidr) - $_cidr = $cidr - } else { - $_cidr = build_cidr_array($netmask) + $real_route_down_template = $route_down_template ? { + undef => $::osfamily ? { + 'Debian' => 'network/route_down-Debian.erb', + default => undef, + }, + default => $route_down_template, } - if $family { - validate_array($family) + if $::osfamily == 'SuSE' { + $networks = keys($routes) + network::mroute::validate_gw { $networks: + routes => $routes, + } } - include ::network - case $::osfamily { 'RedHat': { file { "route-${name}": @@ -165,28 +104,19 @@ owner => 'root', group => 'root', path => "/etc/sysconfig/network-scripts/route-${name}", - content => template('network/route-RedHat.erb'), - notify => $network::manage_config_file_notify, - } - file { "route6-${name}": - ensure => $ensure, - mode => '0644', - owner => 'root', - group => 'root', - path => "/etc/sysconfig/network-scripts/route6-${name}", - content => template('network/route6-RedHat.erb'), - notify => $network::manage_config_file_notify, + content => template($real_route_up_template), + notify => $real_config_file_notify, } - } - 'Suse': { - file { "ifroute-${name}": - ensure => $ensure, - mode => '0644', - owner => 'root', - group => 'root', - path => "/etc/sysconfig/network/ifroute-${name}", - content => template('network/route-Suse.erb'), - notify => $network::manage_config_file_notify, + if $ipv6_routes != {} { + file { "route6-${name}": + ensure => $ensure, + mode => '0644', + owner => 'root', + group => 'root', + path => "/etc/sysconfig/network-scripts/route6-${name}", + content => template('network/route6-RedHat.erb'), + notify => $real_config_file_notify, + } } } 'Debian': { @@ -196,8 +126,8 @@ owner => 'root', group => 'root', path => "/etc/network/if-up.d/z90-route-${name}", - content => template('network/route_up-Debian.erb'), - notify => $network::manage_config_file_notify, + content => template($real_route_up_template), + notify => $real_config_file_notify, } file { "routedown-${name}": ensure => $ensure, @@ -205,10 +135,21 @@ owner => 'root', group => 'root', path => "/etc/network/if-down.d/z90-route-${name}", - content => template('network/route_down-Debian.erb'), - notify => $network::manage_config_file_notify, + content => template($real_route_down_template), + notify => $real_config_file_notify, + } + } + 'SuSE': { + file { "ifroute-${name}": + ensure => $ensure, + mode => '0644', + owner => 'root', + group => 'root', + path => "/etc/sysconfig/network/ifroute-${name}", + content => template($real_route_up_template), + notify => $real_config_file_notify, } } default: { fail('Operating system not supported') } } -} # define network::route +} diff --git a/manifests/routing_table.pp b/manifests/routing_table.pp index 07a106f..39dbef3 100644 --- a/manifests/routing_table.pp +++ b/manifests/routing_table.pp @@ -22,8 +22,8 @@ # define network::routing_table ( - $table_id, - $table = $name + String $table_id, + String $table = $name ) { if ! defined(Concat['/etc/iproute2/rt_tables']) { @@ -35,7 +35,7 @@ concat::fragment { 'rt_tables-base': target => '/etc/iproute2/rt_tables', - source => 'puppet:///modules/network/rt_tables', + source => 'puppet:///modules/network/legacy/rt_tables', } } diff --git a/manifests/rule.pp b/manifests/rule.pp index 19f97b1..f4ffc60 100644 --- a/manifests/rule.pp +++ b/manifests/rule.pp @@ -1,7 +1,3 @@ -# == Definition: network::rule -# -# Configures /etc/sysconfig/networking-scripts/rule-$name on RHEL -# # === Parameters: # # $iprule - required @@ -24,19 +20,12 @@ # # Marcus Furlong # - define network::rule ( - $iprule, - $interface = $name, - $family = undef, - $ensure = 'present' + Array $iprule, + String $interface = $name, + Optional[Array] $family = undef, + Enum['present','absent'] $ensure = 'present', ) { - # Validate our arrays - validate_array($iprule) - - if $family { - validate_array($family) - } include ::network @@ -49,7 +38,7 @@ mode => '0644', path => "/etc/sysconfig/network-scripts/rule-${interface}", content => template('network/rule-RedHat.erb'), - notify => $network::manage_config_file_notify, + notify => $::network::manage_config_file_notify, } file { "rule6-${interface}": ensure => present, @@ -58,7 +47,7 @@ mode => '0644', path => "/etc/sysconfig/network-scripts/rule6-${interface}", content => template('network/rule6-RedHat.erb'), - notify => $network::manage_config_file_notify, + notify => $::network::manage_config_file_notify, } } 'Suse': { @@ -69,7 +58,7 @@ mode => '0644', path => "/etc/sysconfig/network/ifrule-${interface}", content => template('network/rule-RedHat.erb'), - notify => $network::manage_config_file_notify, + notify => $::network::manage_config_file_notify, } } 'Debian': { @@ -80,7 +69,7 @@ group => 'root', path => "/etc/network/if-up.d/z90-rule-${name}", content => template('network/rule_up-Debian.erb'), - notify => $network::manage_config_file_notify, + notify => $::network::manage_config_file_notify, } file { "ruledown-${name}": ensure => $ensure, @@ -89,7 +78,7 @@ group => 'root', path => "/etc/network/if-down.d/z90-rule-${name}", content => template('network/rule_down-Debian.erb'), - notify => $network::manage_config_file_notify, + notify => $::network::manage_config_file_notify, } } default: { fail('Operating system not supported') } diff --git a/metadata.json b/metadata.json index b028741..f71c229 100644 --- a/metadata.json +++ b/metadata.json @@ -1,10 +1,10 @@ { "name": "example42-network", - "version": "3.5.1", - "source": "https://github.com/example42/puppet-network", - "author": "Alessandro Franceschi", + "version": "4.0.1.alpha1", + "author": "example42 Gmbh and others", "summary": "Example42 Network Module", "license": "Apache-2.0", + "source": "https://github.com/example42/puppet-network", "project_page": "https://github.com/example42/puppet-network", "dependencies": [ { @@ -22,7 +22,8 @@ "operatingsystemrelease": [ "5", "6", - "7" + "7", + "8" ] }, { @@ -30,7 +31,8 @@ "operatingsystemrelease": [ "5", "6", - "7" + "7", + "8" ] }, { @@ -38,7 +40,8 @@ "operatingsystemrelease": [ "5", "6", - "7" + "7", + "8" ] }, { @@ -46,7 +49,8 @@ "operatingsystemrelease": [ "5", "6", - "7" + "7", + "8" ] }, { @@ -99,7 +103,10 @@ "requirements": [ { "name": "puppet", - "version_requirement": ">= 3.0.0 <7.0.0" + "version_requirement": ">= 4.0.0 <7.0.0" } - ] + ], + "pdk-version": "1.11.0", + "template-url": "https://github.com/puppetlabs/pdk-templates#1.10.0", + "template-ref": "1.10.0-0-gbba9ac3" } diff --git a/spec/default_facts.yml b/spec/default_facts.yml new file mode 100644 index 0000000..ea1e480 --- /dev/null +++ b/spec/default_facts.yml @@ -0,0 +1,7 @@ +# Use default_module_facts.yml for module specific facts. +# +# Facts specified here will override the values provided by rspec-puppet-facts. +--- +ipaddress: "172.16.254.254" +is_pe: false +macaddress: "AA:AA:AA:AA:AA:AA" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2c6f566..93b25ec 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1 +1,47 @@ require 'puppetlabs_spec_helper/module_spec_helper' +require 'rspec-puppet-facts' + +require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) + +include RspecPuppetFacts + +default_facts = { + puppetversion: Puppet.version, + facterversion: Facter.version, +} + +default_fact_files = [ + File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')), + File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')), +] + +default_fact_files.each do |f| + next unless File.exist?(f) && File.readable?(f) && File.size?(f) + + begin + default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) + rescue => e + RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" + end +end + +RSpec.configure do |c| + c.default_facts = default_facts + c.before :each do + # set to strictest setting for testing + # by default Puppet runs at warning level + Puppet.settings[:strict] = :warning + end + c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] + c.after(:suite) do + end +end + +def ensure_module_defined(module_name) + module_name.split('::').reduce(Object) do |last_module, next_module| + last_module.const_set(next_module, Module.new) unless last_module.const_defined?(next_module, false) + last_module.const_get(next_module, false) + end +end + +# 'spec_overrides' from sync.yml will appear below this line diff --git a/templates/hostname-RedHat.erb b/templates/hostname-RedHat.erb index ba0a82b..58c54e8 100644 --- a/templates/hostname-RedHat.erb +++ b/templates/hostname-RedHat.erb @@ -10,4 +10,4 @@ NOZEROCONF="<%= @nozeroconf %>" NETWORKING_IPV6="<%= @ipv6enable %>" IPV6INIT="<%= @ipv6enable %>" <% end -%> -HOSTNAME="<%= @manage_hostname.split('.').first %>" +HOSTNAME="<%= @manage_hostname %>" diff --git a/templates/interface/Debian.epp b/templates/interface/Debian.epp new file mode 100644 index 0000000..e474731 --- /dev/null +++ b/templates/interface/Debian.epp @@ -0,0 +1,7 @@ +# Interface <%= $params['interface'] %> managed by Puppet +# <%= $params['description'] %> +<%= $params['header'] -%> +<% $params['settings'].each | $k,$v | { -%> + <%= $k %> <%= $v %> +<% } -%> +<%= $params['footer'] -%> diff --git a/templates/interface/RedHat.epp b/templates/interface/RedHat.epp new file mode 100644 index 0000000..15d0d14 --- /dev/null +++ b/templates/interface/RedHat.epp @@ -0,0 +1,7 @@ +# Interface <%= $params['interface'] %> managed by Puppet +# <%= $params['description'] %> +<%= $params['header'] -%> +<% $params['settings'].each | $k,$v | { -%> +<%= $k %>=<%= $v %> +<% } -%> +<%= $params['footer'] -%> diff --git a/templates/interface/Solaris.epp b/templates/interface/Solaris.epp new file mode 100644 index 0000000..a55a091 --- /dev/null +++ b/templates/interface/Solaris.epp @@ -0,0 +1,2 @@ +# File managed by Puppet +<%= $ipv4_address %> netmask <%= $ipv4_netmask %> diff --git a/templates/interface/Suse.epp b/templates/interface/Suse.epp new file mode 100644 index 0000000..15d0d14 --- /dev/null +++ b/templates/interface/Suse.epp @@ -0,0 +1,7 @@ +# Interface <%= $params['interface'] %> managed by Puppet +# <%= $params['description'] %> +<%= $params['header'] -%> +<% $params['settings'].each | $k,$v | { -%> +<%= $k %>=<%= $v %> +<% } -%> +<%= $params['footer'] -%> diff --git a/templates/legacy/hostname-Debian.erb b/templates/legacy/hostname-Debian.erb new file mode 100644 index 0000000..a837783 --- /dev/null +++ b/templates/legacy/hostname-Debian.erb @@ -0,0 +1 @@ +<%= @manage_hostname.split('.').first %> diff --git a/templates/legacy/hostname-RedHat.erb b/templates/legacy/hostname-RedHat.erb new file mode 100644 index 0000000..ba0a82b --- /dev/null +++ b/templates/legacy/hostname-RedHat.erb @@ -0,0 +1,13 @@ +# File Managed by Puppet +NETWORKING="yes" +<% if @gateway -%> +GATEWAY="<%= @gateway %>" +<% end -%> +<% if @nozeroconf -%> +NOZEROCONF="<%= @nozeroconf %>" +<% end -%> +<% if @ipv6enable -%> +NETWORKING_IPV6="<%= @ipv6enable %>" +IPV6INIT="<%= @ipv6enable %>" +<% end -%> +HOSTNAME="<%= @manage_hostname.split('.').first %>" diff --git a/templates/interface/Debian.erb b/templates/legacy/interface/Debian.erb similarity index 100% rename from templates/interface/Debian.erb rename to templates/legacy/interface/Debian.erb diff --git a/templates/interface/RedHat.erb b/templates/legacy/interface/RedHat.erb similarity index 100% rename from templates/interface/RedHat.erb rename to templates/legacy/interface/RedHat.erb diff --git a/templates/interface/Suse.erb b/templates/legacy/interface/Suse.erb similarity index 100% rename from templates/interface/Suse.erb rename to templates/legacy/interface/Suse.erb diff --git a/templates/mroute-RedHat.erb b/templates/legacy/mroute-RedHat.erb similarity index 100% rename from templates/mroute-RedHat.erb rename to templates/legacy/mroute-RedHat.erb diff --git a/templates/mroute-SuSE.erb b/templates/legacy/mroute-SuSE.erb similarity index 100% rename from templates/mroute-SuSE.erb rename to templates/legacy/mroute-SuSE.erb diff --git a/templates/mroute_down-Debian.erb b/templates/legacy/mroute_down-Debian.erb similarity index 100% rename from templates/mroute_down-Debian.erb rename to templates/legacy/mroute_down-Debian.erb diff --git a/templates/mroute_up-Debian.erb b/templates/legacy/mroute_up-Debian.erb similarity index 100% rename from templates/mroute_up-Debian.erb rename to templates/legacy/mroute_up-Debian.erb diff --git a/templates/legacy/route-RedHat.erb b/templates/legacy/route-RedHat.erb new file mode 100644 index 0000000..0c33f23 --- /dev/null +++ b/templates/legacy/route-RedHat.erb @@ -0,0 +1,6 @@ +### +### File managed by Puppet +### +<%- (0..(@ipaddress.length-1)).each do |id| -%> +<%- if @family and @family[id] != 'inet6' -%><%= @ipaddress[id] %>/<%= @_cidr[id] %><%- if @gateway and @gateway[id] -%> via <%= @gateway[id] %><%- end -%> dev <%= @interface %><%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %><%- if @mtu and @mtu[id] -%> mtu <%= @mtu[id] %><% end %> +<%- end -%><%- end %> diff --git a/templates/legacy/route-Suse.erb b/templates/legacy/route-Suse.erb new file mode 100644 index 0000000..39bd9dd --- /dev/null +++ b/templates/legacy/route-Suse.erb @@ -0,0 +1,6 @@ +### +#### File managed by Puppet +#### +<%- (0..(@ipaddress.length-1)).each do |id| -%> +<%= @ipaddress[id] %><%- if @gateway and @gateway[id] -%> <%= @gateway[id] %><%- else -%> -<%- end -%> <%= @netmask[id] %> <%= @interface %><%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %><%- if @mtu and @mtu[id] -%> mtu <%= @mtu[id] %><% end %> +<%- end %> diff --git a/templates/legacy/route6-RedHat.erb b/templates/legacy/route6-RedHat.erb new file mode 100644 index 0000000..f24a6e1 --- /dev/null +++ b/templates/legacy/route6-RedHat.erb @@ -0,0 +1,6 @@ +### +### File managed by Puppet +### +<%- (0..(@ipaddress.length-1)).each do |id| -%> +<%- if @family and @family[id] == 'inet6' -%><%= @ipaddress[id] %>/<%= @_cidr[id] %><%- if @gateway and @gateway[id] -%> via <%= @gateway[id] %><%- end -%> dev <%= @interface %><%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %> +<%- end -%><%- end %> diff --git a/templates/legacy/route_down-Debian.erb b/templates/legacy/route_down-Debian.erb new file mode 100644 index 0000000..7c06013 --- /dev/null +++ b/templates/legacy/route_down-Debian.erb @@ -0,0 +1,12 @@ +#!/bin/bash +# +### File managed by Puppet +# +if [ "$IFACE" = "<%= @interface -%>" ] || [ "$IFACE" = "--all" ]; then +<%- (0..(@ipaddress.length-1)).each do |id| -%> + if ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> route show <%- if @table and @table[id] -%> table <%= @table[id] %><% end %> | grep -qP "<%= @ipaddress[id] %><%- if @_cidr and @_cidr[id] and @_cidr[id] != 32 -%>/<%= @_cidr[id] %><%- if @ipaddress[id] == '0.0.0.0' and @_cidr[id] == 0 %>|default<%- end %><%- end -%> " + then + ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> route del <%= @ipaddress[id] %>/<%= @_cidr[id] %><%- if @gateway and @gateway[id] -%> via <%= @gateway[id] %><%- end -%> dev <%= @interface %> <%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %><%- if @mtu and @mtu[id] -%> mtu <%= @mtu[id] %><% end %> + fi +<%- end -%> +fi diff --git a/templates/legacy/route_up-Debian.erb b/templates/legacy/route_up-Debian.erb new file mode 100644 index 0000000..7dcfbc0 --- /dev/null +++ b/templates/legacy/route_up-Debian.erb @@ -0,0 +1,12 @@ +#!/bin/bash +# +### File managed by Puppet +# +if [ "$IFACE" = "<%= @interface -%>" ] || [ "$IFACE" = "--all" ]; then +<%- (0..(@ipaddress.length-1)).each do |id| -%> + if ! ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> route show <%- if @table and @table[id] -%> table <%= @table[id] %><% end %> | grep -qP "<%= @ipaddress[id] %><%- if @_cidr and @_cidr[id] and @_cidr[id] != 32 -%>/<%= @_cidr[id] %><%- if @ipaddress[id] == '0.0.0.0' and @_cidr[id] == 0 %>|default<%- end %><%- end -%> " + then + ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> route add <%= @ipaddress[id] %>/<%= @_cidr[id] %><%- if @gateway and @gateway[id] -%> via <%= @gateway[id] %><%- end -%> dev <%= @interface %> <%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %><%- if @mtu and @mtu[id] -%> mtu <%= @mtu[id] %><% end %> + fi +<%- end -%> +fi diff --git a/templates/legacy/rule-RedHat.erb b/templates/legacy/rule-RedHat.erb new file mode 100644 index 0000000..103d0fa --- /dev/null +++ b/templates/legacy/rule-RedHat.erb @@ -0,0 +1,8 @@ +### +### File managed by Puppet +### +<%- (0..(@iprule.length-1)).each do |id| -%> +<%- if @family and @family[id] != 'inet6' -%> +<%= @iprule[id] %> +<% end -%> +<%- end -%> diff --git a/templates/legacy/rule6-RedHat.erb b/templates/legacy/rule6-RedHat.erb new file mode 100644 index 0000000..7c0bfbd --- /dev/null +++ b/templates/legacy/rule6-RedHat.erb @@ -0,0 +1,8 @@ +### +### File managed by Puppet +### +<%- (0..(@iprule.length-1)).each do |id| -%> +<%- if @family and @family[id] == 'inet6' -%> +<%= @iprule[id] %> +<% end -%> +<%- end -%> diff --git a/templates/legacy/rule_down-Debian.erb b/templates/legacy/rule_down-Debian.erb new file mode 100644 index 0000000..20e6b15 --- /dev/null +++ b/templates/legacy/rule_down-Debian.erb @@ -0,0 +1,12 @@ +#!/bin/bash +# +### File managed by Puppet +# +if [ "$IFACE" = "<%= @interface -%>" ] || [ "$IFACE" = "--all" ]; then +<%- (0..(@iprule.length-1)).each do |id| -%> + if ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> rule show | grep -qF "<%= @iprule[id] %>" + then + ip <%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> rule del <%= @iprule[id] %> + fi +<%- end -%> +fi diff --git a/templates/legacy/rule_up-Debian.erb b/templates/legacy/rule_up-Debian.erb new file mode 100644 index 0000000..0ba92be --- /dev/null +++ b/templates/legacy/rule_up-Debian.erb @@ -0,0 +1,12 @@ +#!/bin/bash +# +### File managed by Puppet +# +if [ "$IFACE" = "<%= @interface -%>" ] || [ "$IFACE" = "--all" ]; then +<%- (0..(@iprule.length-1)).each do |id| -%> + if ! ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> rule show | grep -qF "<%= @iprule[id] %>" + then + ip <%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> rule add <%= @iprule[id] %> + fi +<%- end -%> +fi diff --git a/templates/legacy/spec.conf b/templates/legacy/spec.conf new file mode 100644 index 0000000..5cd7291 --- /dev/null +++ b/templates/legacy/spec.conf @@ -0,0 +1,5 @@ +# This is a template used only for rspec tests + +# Custom Options +<%= @config_file_options_hash['opt_a'] %> +<%= @config_file_options_hash['opt_b'] %> diff --git a/templates/route-RedHat.erb b/templates/route-RedHat.erb index 0c33f23..c1fd76c 100644 --- a/templates/route-RedHat.erb +++ b/templates/route-RedHat.erb @@ -1,6 +1,12 @@ ### ### File managed by Puppet ### -<%- (0..(@ipaddress.length-1)).each do |id| -%> -<%- if @family and @family[id] != 'inet6' -%><%= @ipaddress[id] %>/<%= @_cidr[id] %><%- if @gateway and @gateway[id] -%> via <%= @gateway[id] %><%- end -%> dev <%= @interface %><%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %><%- if @mtu and @mtu[id] -%> mtu <%= @mtu[id] %><% end %> -<%- end -%><%- end %> +<% @routes.each do |net,gw| -%> +<%= net -%> +<% + if gw.kind_of?(Array) + gw.each do | g | %> nexthop via <%= g %><% end %> + <%- elsif /^\d/.match(gw) %> via <%= gw %> + <%- else %> dev <%= gw %> + <%- end -%> +<% end -%> diff --git a/templates/route-Suse.erb b/templates/route-Suse.erb index 39bd9dd..c1fd76c 100644 --- a/templates/route-Suse.erb +++ b/templates/route-Suse.erb @@ -1,6 +1,12 @@ ### -#### File managed by Puppet -#### -<%- (0..(@ipaddress.length-1)).each do |id| -%> -<%= @ipaddress[id] %><%- if @gateway and @gateway[id] -%> <%= @gateway[id] %><%- else -%> -<%- end -%> <%= @netmask[id] %> <%= @interface %><%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %><%- if @mtu and @mtu[id] -%> mtu <%= @mtu[id] %><% end %> -<%- end %> +### File managed by Puppet +### +<% @routes.each do |net,gw| -%> +<%= net -%> +<% + if gw.kind_of?(Array) + gw.each do | g | %> nexthop via <%= g %><% end %> + <%- elsif /^\d/.match(gw) %> via <%= gw %> + <%- else %> dev <%= gw %> + <%- end -%> +<% end -%> diff --git a/templates/route6-RedHat.erb b/templates/route6-RedHat.erb index f24a6e1..c81a376 100644 --- a/templates/route6-RedHat.erb +++ b/templates/route6-RedHat.erb @@ -1,6 +1,12 @@ ### ### File managed by Puppet ### -<%- (0..(@ipaddress.length-1)).each do |id| -%> -<%- if @family and @family[id] == 'inet6' -%><%= @ipaddress[id] %>/<%= @_cidr[id] %><%- if @gateway and @gateway[id] -%> via <%= @gateway[id] %><%- end -%> dev <%= @interface %><%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %> -<%- end -%><%- end %> +<% @ipv6_routes.each do |net,gw| -%> +<%= net -%> +<% + if gw.kind_of?(Array) + gw.each do | g | %> nexthop via <%= g %><% end %> + <%- elsif /^\d/.match(gw) %> via <%= gw %> + <%- else %> dev <%= gw %> + <%- end -%> +<% end -%> diff --git a/templates/route_down-Debian.erb b/templates/route_down-Debian.erb index 7c06013..b216311 100644 --- a/templates/route_down-Debian.erb +++ b/templates/route_down-Debian.erb @@ -1,12 +1,18 @@ #!/bin/bash # +### ### File managed by Puppet -# +### if [ "$IFACE" = "<%= @interface -%>" ] || [ "$IFACE" = "--all" ]; then -<%- (0..(@ipaddress.length-1)).each do |id| -%> - if ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> route show <%- if @table and @table[id] -%> table <%= @table[id] %><% end %> | grep -qP "<%= @ipaddress[id] %><%- if @_cidr and @_cidr[id] and @_cidr[id] != 32 -%>/<%= @_cidr[id] %><%- if @ipaddress[id] == '0.0.0.0' and @_cidr[id] == 0 %>|default<%- end %><%- end -%> " +<% @routes.each do |net,gw| -%> + if ip route show | grep -qF "<%= net %> " then - ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> route del <%= @ipaddress[id] %>/<%= @_cidr[id] %><%- if @gateway and @gateway[id] -%> via <%= @gateway[id] %><%- end -%> dev <%= @interface %> <%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %><%- if @mtu and @mtu[id] -%> mtu <%= @mtu[id] %><% end %> + ip route del <% if @table -%>table <%= @table %> <% end -%><%= net %><% + if gw.kind_of?(Array) + gw.each do | g | %> nexthop via <%= g %><% end %> + <%- elsif /^\d/.match(gw) %> via <%= gw %> + <%- else %> dev <%= gw %> + <%- end -%> fi -<%- end -%> +<% end -%> fi diff --git a/templates/route_up-Debian.erb b/templates/route_up-Debian.erb index 7dcfbc0..875d6d1 100644 --- a/templates/route_up-Debian.erb +++ b/templates/route_up-Debian.erb @@ -1,12 +1,18 @@ #!/bin/bash # +### ### File managed by Puppet -# +### if [ "$IFACE" = "<%= @interface -%>" ] || [ "$IFACE" = "--all" ]; then -<%- (0..(@ipaddress.length-1)).each do |id| -%> - if ! ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> route show <%- if @table and @table[id] -%> table <%= @table[id] %><% end %> | grep -qP "<%= @ipaddress[id] %><%- if @_cidr and @_cidr[id] and @_cidr[id] != 32 -%>/<%= @_cidr[id] %><%- if @ipaddress[id] == '0.0.0.0' and @_cidr[id] == 0 %>|default<%- end %><%- end -%> " +<% @routes.each do |net,gw| -%> + if ! ip route show | grep -qF "<%= net %> " then - ip<%- if @family and @family[id] == 'inet6' -%> -6<%- end -%> route add <%= @ipaddress[id] %>/<%= @_cidr[id] %><%- if @gateway and @gateway[id] -%> via <%= @gateway[id] %><%- end -%> dev <%= @interface %> <%- if @scope and @scope[id] -%> scope <%= @scope[id] %><%- end -%><%- if @source and @source[id] -%> src <%= @source[id] %><%- end -%><%- if @table and @table[id] -%> table <%= @table[id] %><% end %><%- if @metric and @metric[id] -%> metric <%= @metric[id] %><% end %><%- if @mtu and @mtu[id] -%> mtu <%= @mtu[id] %><% end %> + ip route add <% if @table -%>table <%= @table %> <% end -%><%= net %><% + if gw.kind_of?(Array) + gw.each do | g | %> nexthop via <%= g %><% end %> + <%- elsif /^\d/.match(gw) %> via <%= gw %> + <%- else %> dev <%= gw %> + <%- end -%> fi -<%- end -%> +<% end -%> fi diff --git a/types/netplanaddresses.pp b/types/netplanaddresses.pp new file mode 100644 index 0000000..ad4d4a3 --- /dev/null +++ b/types/netplanaddresses.pp @@ -0,0 +1,10 @@ +type Network::NetplanAddresses = Array[ + Variant[ + Stdlib::IP::Address::V4::CIDR, + Variant[ + Stdlib::IP::Address::V6::Full, + Stdlib::IP::Address::V6::Compressed, + Stdlib::IP::Address::V6::Alternative, + ] + ] +] diff --git a/types/netplandhcp.pp b/types/netplandhcp.pp new file mode 100644 index 0000000..9b1616f --- /dev/null +++ b/types/netplandhcp.pp @@ -0,0 +1,4 @@ +type Network::NetplanDhcp = Variant[ + Boolean, + Enum['yes','no','true','false'] +]