From 17f6c1077093b62347e76a8b6b8126dacd62aa0e Mon Sep 17 00:00:00 2001 From: Steven Hillman Date: Wed, 14 Oct 2015 15:12:33 -0700 Subject: [PATCH] Enhance bridge preparation to support tagged management ports Add support for creating a bridge when the management port is tagged. Also allows use of management ports that don't have IPs. Change-Id: I9810fe68b62e690c5e206898eec1320b15eac24b --- manifests/init.pp | 22 ++-- manifests/pkgprep_ovscfg.pp | 85 ++++++++---- spec/classes/n1kv_vsm_pkgprep_ovscfg_spec.rb | 132 ++++++++++++++++++- 3 files changed, 200 insertions(+), 39 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index c6fb9b7..ddcd42d 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -49,6 +49,11 @@ # (optional) If set, provides randomization for the MAC addresses for the VSM VM(s). # Should be a (random) hexadecimal number of at least 7 digits (more is fine). # +# [*phy_bridge_vlan*] +# (optional) In the case that the management interface is a bridge with a tagged +# uplink port, the VLAN tag for that uplink port can be provided which will +# be applied on the patch port connecting vsm-br and the management bridge. +# class n1k_vsm( $n1kv_source = '', $n1kv_version = 'latest', @@ -62,7 +67,8 @@ class n1k_vsm( $vsm_mgmt_gateway, $pacemaker_control = false, $existing_bridge = false, - $vsm_mac_base = '' + $vsm_mac_base = '', + $phy_bridge_vlan = 0, ) { if($::osfamily != 'Redhat') { @@ -103,18 +109,14 @@ class n1k_vsm( $ovsbridge = 'vsm-br' #VSM installation will be done only once. Will not respond to puppet sync - $_phy_if_bridge = regsubst($n1k_vsm::phy_if_bridge, '[.:-]+', '_', 'G') - $_phy_ip_addr = inline_template("<%= scope.lookupvar('::ipaddress_${_phy_if_bridge}') %>") - if $_phy_ip_addr != '' { - $phy_ip_addr = inline_template("<%= scope.lookupvar('::ipaddress_${_phy_if_bridge}') %>") - $phy_ip_mask = inline_template("<%= scope.lookupvar('::netmask_${_phy_if_bridge}') %>") - $gw_intf = $n1k_vsm::phy_gateway - include ::n1k_vsm::pkgprep_ovscfg + $_check_phy_if_bridge = regsubst($n1k_vsm::phy_if_bridge, '[.:-]+', '_', 'G') + $_phy_mac_addr = inline_template("<%= scope.lookupvar('::macaddress_${_check_phy_if_bridge}') %>") + if $_phy_mac_addr != '' { + include ::n1k_vsm::pkgprep_ovscfg } notify {"Arg: intf ${phy_if_bridge} vsm_role ${vsm_role} domainid ${vsm_domain_id}" : withpath => true} - notify {"ip ${phy_ip_addr} mask ${phy_ip_mask} gw ${n1k_vsm::phy_gateway}" : withpath => true} - notify {"gw_dv ${gw_intf} ovs ${ovsbridge} vsmname ${n1k_vsm::vsmname}" : withpath => true} + notify {"ovs ${ovsbridge} vsmname ${n1k_vsm::vsmname}" : withpath => true} notify {"mgmtip ${n1k_vsm::mgmtip} vsm_mask ${n1k_vsm::mgmtnetmask} vsm_gw ${n1k_vsm::mgmtgateway}": withpath => false} include ::n1k_vsm::vsmprep diff --git a/manifests/pkgprep_ovscfg.pp b/manifests/pkgprep_ovscfg.pp index ec0a444..8efec39 100644 --- a/manifests/pkgprep_ovscfg.pp +++ b/manifests/pkgprep_ovscfg.pp @@ -62,34 +62,68 @@ class n1k_vsm::pkgprep_ovscfg } notify { "Debug br ${n1k_vsm::ovsbridge} intf ${n1k_vsm::phy_if_bridge} ." : withpath => true } - notify { "Debug ${n1k_vsm::vsmname} ip ${n1k_vsm::phy_ip_addr} mask ${n1k_vsm::phy_ip_mask} gw_intf ${n1k_vsm::gw_intf}" : withpath => true } $_ovsbridge = regsubst($n1k_vsm::ovsbridge, '[.:-]+', '_', 'G') $_ovsbridge_mac = inline_template("<%= scope.lookupvar('::macaddress_${_ovsbridge}') %>") # Check if we've already configured the vsm bridge, skip configuration if so if ($_ovsbridge_mac == '') { - # Modify Ovs bridge inteface configuation file - augeas { 'Augeas_modify_ifcfg-ovsbridge': - name => $n1k_vsm::ovsbridge, - context => "/files/etc/sysconfig/network-scripts/ifcfg-${n1k_vsm::ovsbridge}", - changes => [ - 'set TYPE OVSBridge', - "set DEVICE ${n1k_vsm::ovsbridge}", - 'set DEVICETYPE ovs', - "set OVSREQUIRES ${n1k_vsm::ovsbridge}", - 'set NM_CONTROLLED no', - 'set BOOTPROTO none', - 'set ONBOOT yes', - 'set DEFROUTE yes', - 'set MTU 1500', - "set NAME ${n1k_vsm::ovsbridge}", - "set IPADDR ${n1k_vsm::phy_ip_addr}", - "set NETMASK ${n1k_vsm::phy_ip_mask}", - "set GATEWAY ${n1k_vsm::phy_gateway}", - 'set USERCTL no', - ], + + #Gather info from the port/bridge including IP if needed + $_phy_if_bridge = regsubst($n1k_vsm::phy_if_bridge, '[.:-]+', '_', 'G') + $_phy_ip_addr = inline_template("<%= scope.lookupvar('::ipaddress_${_phy_if_bridge}') %>") + if $_phy_ip_addr != '' { + $phy_ip_addr = inline_template("<%= scope.lookupvar('::ipaddress_${_phy_if_bridge}') %>") + $phy_ip_mask = inline_template("<%= scope.lookupvar('::netmask_${_phy_if_bridge}') %>") + $gw_intf = $n1k_vsm::phy_gateway + + notify {"ip ${phy_ip_addr} mask ${phy_ip_mask} gw ${n1k_vsm::phy_gateway} gw_dv ${gw_intf}" : withpath => true} + + # Modify Ovs bridge inteface configuation file (including IP) + augeas { 'Augeas_modify_ifcfg-ovsbridge': + name => $n1k_vsm::ovsbridge, + context => "/files/etc/sysconfig/network-scripts/ifcfg-${n1k_vsm::ovsbridge}", + changes => [ + 'set TYPE OVSBridge', + "set DEVICE ${n1k_vsm::ovsbridge}", + 'set DEVICETYPE ovs', + "set OVSREQUIRES ${n1k_vsm::ovsbridge}", + 'set NM_CONTROLLED no', + 'set BOOTPROTO none', + 'set ONBOOT yes', + 'set DEFROUTE yes', + 'set MTU 1500', + "set NAME ${n1k_vsm::ovsbridge}", + "set IPADDR ${phy_ip_addr}", + "set NETMASK ${phy_ip_mask}", + "set GATEWAY ${n1k_vsm::phy_gateway}", + 'set USERCTL no', + ], + } + } elsif ($n1k_vsm::existing_bridge) { + # Modify Ovs bridge inteface configuation file (without IP) + augeas { 'Augeas_modify_ifcfg-ovsbridge': + name => $n1k_vsm::ovsbridge, + context => "/files/etc/sysconfig/network-scripts/ifcfg-${n1k_vsm::ovsbridge}", + changes => [ + 'set TYPE OVSBridge', + "set DEVICE ${n1k_vsm::ovsbridge}", + 'set DEVICETYPE ovs', + "set OVSREQUIRES ${n1k_vsm::ovsbridge}", + 'set NM_CONTROLLED no', + 'set BOOTPROTO none', + 'set ONBOOT yes', + 'set DEFROUTE yes', + 'set MTU 1500', + "set NAME ${n1k_vsm::ovsbridge}", + 'set USERCTL no', + ], + } + } else { + # Error out here due to invalid interface specification + fail('Interface to be bridged for VSM must have IP address') } + exec { 'Flap_n1kv_bridge': command => "/sbin/ifdown ${n1k_vsm::ovsbridge} && /sbin/ifup ${n1k_vsm::ovsbridge}", require => Augeas['Augeas_modify_ifcfg-ovsbridge'], @@ -98,6 +132,7 @@ class n1k_vsm::pkgprep_ovscfg if !($n1k_vsm::existing_bridge) { # If there isn't an existing bridge, the interface is a port, and we # need to add it to vsm-br + # Modify Physical Interface config file augeas { 'Augeas_modify_ifcfg-phy_if_bridge': name => $n1k_vsm::phy_if_bridge, @@ -132,8 +167,14 @@ class n1k_vsm::pkgprep_ovscfg command => "/bin/ovs-vsctl --may-exist add-port ${n1k_vsm::ovsbridge} ${n1k_vsm::ovsbridge}-${n1k_vsm::phy_if_bridge} -- set Interface ${n1k_vsm::ovsbridge}-${n1k_vsm::phy_if_bridge} type=patch options:peer=${n1k_vsm::phy_if_bridge}-${n1k_vsm::ovsbridge}", require => Exec['Flap_n1kv_bridge'], } + if ($n1k_vsm::phy_bridge_vlan > 0) and ($n1k_vsm::phy_bridge_vlan < 4096) { + exec { 'Tag_patch_port': + command => "/bin/ovs-vsctl set port ${n1k_vsm::phy_if_bridge}-${n1k_vsm::ovsbridge} tag=${n1k_vsm::phy_bridge_vlan}", + require => Exec['Create_patch_port_on_existing_bridge'], + } + } } - } # endif of if "${n1k_vsm::gw_intf}" != "${n1k_vsm::ovsbridge}" or ($n1k_vsm::existing_bridge == 'true') + } # endif of if ($_ovsbridge_mac == '') } 'Ubuntu': { } diff --git a/spec/classes/n1kv_vsm_pkgprep_ovscfg_spec.rb b/spec/classes/n1kv_vsm_pkgprep_ovscfg_spec.rb index 7a84829..18fb7dd 100644 --- a/spec/classes/n1kv_vsm_pkgprep_ovscfg_spec.rb +++ b/spec/classes/n1kv_vsm_pkgprep_ovscfg_spec.rb @@ -37,6 +37,12 @@ describe 'n1k_vsm::pkgprep_ovscfg' do existing_bridge => false, }" end + let :facts do + { + :ipaddress_eth0 => '1.1.1.1', + :osfamily => 'RedHat' + } + end it 'should require vswitch::ovs' do is_expected.to contain_class('vswitch::ovs') @@ -52,7 +58,7 @@ describe 'n1k_vsm::pkgprep_ovscfg' do it 'flap bridge' do is_expected.to contain_exec('Flap_n1kv_bridge').with( 'command' => '/sbin/ifdown vsm-br && /sbin/ifup vsm-br', - ) + ).that_requires('Augeas[Augeas_modify_ifcfg-ovsbridge]') end it 'attach phy if port to bridge' do @@ -65,14 +71,14 @@ describe 'n1k_vsm::pkgprep_ovscfg' do it 'flap port' do is_expected.to contain_exec('Flap_n1kv_phy_if').with( 'command' => '/sbin/ifdown eth0 && /sbin/ifup eth0', - ) + ).that_requires('Augeas[Augeas_modify_ifcfg-phy_if_bridge]') end end context 'for existing bridge' do let :pre_condition do "class { 'n1k_vsm': - phy_if_bridge => 'br-ex', + phy_if_bridge => 'br_ex', phy_gateway => '1.1.1.3', vsm_domain_id => '1', vsm_admin_passwd => 'secrete', @@ -82,6 +88,12 @@ describe 'n1k_vsm::pkgprep_ovscfg' do existing_bridge => true, }" end + let :facts do + { + :ipaddress_br_ex => '1.1.1.6', + :osfamily => 'RedHat' + } + end it 'should require vswitch::ovs' do is_expected.to contain_class('vswitch::ovs') @@ -97,20 +109,126 @@ describe 'n1k_vsm::pkgprep_ovscfg' do it 'flap bridge' do is_expected.to contain_exec('Flap_n1kv_bridge').with( 'command' => '/sbin/ifdown vsm-br && /sbin/ifup vsm-br', - ) + ).that_requires('Augeas[Augeas_modify_ifcfg-ovsbridge]') end it 'create patch port on existing bridge' do is_expected.to contain_exec('Create_patch_port_on_existing_bridge').with( - 'command' => '/bin/ovs-vsctl --may-exist add-port br-ex br-ex-vsm-br -- set Interface br-ex-vsm-br type=patch options:peer=vsm-br-br-ex' - ) + 'command' => '/bin/ovs-vsctl --may-exist add-port br_ex br_ex-vsm-br -- set Interface br_ex-vsm-br type=patch options:peer=vsm-br-br_ex' + ).that_requires('Exec[Flap_n1kv_bridge]') end it 'create patch port on vsm bridge' do is_expected.to contain_exec('Create_patch_port_on_vsm_bridge').with( - 'command' => '/bin/ovs-vsctl --may-exist add-port vsm-br vsm-br-br-ex -- set Interface vsm-br-br-ex type=patch options:peer=br-ex-vsm-br' + 'command' => '/bin/ovs-vsctl --may-exist add-port vsm-br vsm-br-br_ex -- set Interface vsm-br-br_ex type=patch options:peer=br_ex-vsm-br' + ).that_requires('Exec[Flap_n1kv_bridge]') + end + end + + context 'for existing bridge no ip' do + let :pre_condition do + "class { 'n1k_vsm': + phy_if_bridge => 'br_ex', + phy_gateway => '1.1.1.3', + vsm_domain_id => '1', + vsm_admin_passwd => 'secrete', + vsm_mgmt_ip => '1.1.1.1', + vsm_mgmt_netmask => '255.255.255.0', + vsm_mgmt_gateway => '1.1.1.2', + existing_bridge => true, + }" + end + let :facts do + { + :osfamily => 'RedHat' + } + end + + it 'should require vswitch::ovs' do + is_expected.to contain_class('vswitch::ovs') + end + + it 'create ovs bridge' do + is_expected.to contain_augeas('Augeas_modify_ifcfg-ovsbridge').with( + 'name' => 'vsm-br', + 'context' => '/files/etc/sysconfig/network-scripts/ifcfg-vsm-br', ) end + + it 'flap bridge' do + is_expected.to contain_exec('Flap_n1kv_bridge').with( + 'command' => '/sbin/ifdown vsm-br && /sbin/ifup vsm-br', + ).that_requires('Augeas[Augeas_modify_ifcfg-ovsbridge]') + end + + it 'create patch port on existing bridge' do + is_expected.to contain_exec('Create_patch_port_on_existing_bridge').with( + 'command' => '/bin/ovs-vsctl --may-exist add-port br_ex br_ex-vsm-br -- set Interface br_ex-vsm-br type=patch options:peer=vsm-br-br_ex' + ).that_requires('Exec[Flap_n1kv_bridge]') + end + + it 'create patch port on vsm bridge' do + is_expected.to contain_exec('Create_patch_port_on_vsm_bridge').with( + 'command' => '/bin/ovs-vsctl --may-exist add-port vsm-br vsm-br-br_ex -- set Interface vsm-br-br_ex type=patch options:peer=br_ex-vsm-br' + ).that_requires('Exec[Flap_n1kv_bridge]') + end + end + + context 'for existing bridge tagged' do + let :pre_condition do + "class { 'n1k_vsm': + phy_if_bridge => 'br_ex', + phy_gateway => '1.1.1.3', + vsm_domain_id => '1', + vsm_admin_passwd => 'secrete', + vsm_mgmt_ip => '1.1.1.1', + vsm_mgmt_netmask => '255.255.255.0', + vsm_mgmt_gateway => '1.1.1.2', + existing_bridge => true, + phy_bridge_vlan => 100, + }" + end + let :facts do + { + :ipaddress_br_ex => '1.1.1.6', + :osfamily => 'RedHat' + } + end + + it 'should require vswitch::ovs' do + is_expected.to contain_class('vswitch::ovs') + end + + it 'create ovs bridge' do + is_expected.to contain_augeas('Augeas_modify_ifcfg-ovsbridge').with( + 'name' => 'vsm-br', + 'context' => '/files/etc/sysconfig/network-scripts/ifcfg-vsm-br', + ) + end + + it 'flap bridge' do + is_expected.to contain_exec('Flap_n1kv_bridge').with( + 'command' => '/sbin/ifdown vsm-br && /sbin/ifup vsm-br', + ).that_requires('Augeas[Augeas_modify_ifcfg-ovsbridge]') + end + + it 'create patch port on existing bridge' do + is_expected.to contain_exec('Create_patch_port_on_existing_bridge').with( + 'command' => '/bin/ovs-vsctl --may-exist add-port br_ex br_ex-vsm-br -- set Interface br_ex-vsm-br type=patch options:peer=vsm-br-br_ex' + ).that_requires('Exec[Flap_n1kv_bridge]') + end + + it 'create patch port on vsm bridge' do + is_expected.to contain_exec('Create_patch_port_on_vsm_bridge').with( + 'command' => '/bin/ovs-vsctl --may-exist add-port vsm-br vsm-br-br_ex -- set Interface vsm-br-br_ex type=patch options:peer=br_ex-vsm-br' + ).that_requires('Exec[Flap_n1kv_bridge]') + end + + it 'tag patch port' do + is_expected.to contain_exec('Tag_patch_port').with( + 'command' => '/bin/ovs-vsctl set port br_ex-vsm-br tag=100' + ).that_requires('Exec[Create_patch_port_on_existing_bridge]') + end end end