diff --git a/examples/cisco_ml2.pp b/examples/cisco_ml2.pp new file mode 100644 index 000000000..9d2efe623 --- /dev/null +++ b/examples/cisco_ml2.pp @@ -0,0 +1,64 @@ +class { '::neutron': + enabled => true, + bind_host => '127.0.0.1', + rabbit_host => '127.0.0.1', + rabbit_user => 'neutron', + rabbit_password => 'rabbit_secret', + verbose => true, + debug => true, +} + +class { '::neutron::server': + auth_uri => 'http://127.0.0.1:5000', + auth_password => 'keystone_secret', +} + +class { '::neutron::plugins::ml2': + type_drivers => ['vlan', 'nexus_vxlan'], + tenant_network_types => ['nexus_vxlan'], + network_vlan_ranges => ['physnet:2000:2020'], + mechanism_drivers => ['openvswitch', 'cisco_ucsm', 'cisco_nexus'], +} + +class {'::neutron::plugins::ml2::cisco::ucsm': + ucsm_ip => '127.0.0.1', + ucsm_username => 'admin', + ucsm_password => 'password', + ucsm_host_list => 'host1:profile1, host2:profile2', +} + +class {'::neutron::plugins::ml2::cisco::nexus': + managed_physical_network => 'physnet', + nexus_config => { + 'n9372-1' => { + 'username' => 'admin', + 'password' => 'password', + 'ssh_port' => 22, + 'ip_address' => '127.0.0.1', + 'nve_src_intf' => 1, + 'physnet' => 'physnet', + 'servers' => { + 'control1' => 'ethernet:1/1', + 'control2' => 'ethernet:1/2' + } + }, + 'n9372-2' => { + 'username' => 'admin', + 'password' => 'password', + 'ssh_port' => 22, + 'ip_address' => '127.0.0.1', + 'nve_src_intf' => 1, + 'physnet' => 'physnet', + 'servers' => { + 'compute1' => 'ethernet:1/1', + 'compute2' => 'ethernet:1/2' + } + } + }, +} + +class {'::neutron::plugins::ml2::cisco::type_nexus_vxlan': + vni_ranges => '20000:22000', + mcast_ranges => '224.0.0.1:224.0.0.4', +} + diff --git a/manifests/params.pp b/manifests/params.pp index 8b817651c..d7819a734 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -27,9 +27,10 @@ class neutron::params { $sriov_nic_agent_service = 'neutron-sriov-nic-agent' $sriov_nic_agent_package = 'openstack-neutron-sriov-nic-agent' - $cisco_server_package = 'openstack-neutron-cisco' - $cisco_config_file = '/etc/neutron/plugins/cisco/cisco_plugins.ini' - $cisco_ml2_config_file = '/etc/neutron/plugins/ml2/ml2_conf_cisco.ini' + $cisco_server_package = 'openstack-neutron-cisco' + $cisco_config_file = '/etc/neutron/plugins/cisco/cisco_plugins.ini' + # Add templated Cisco Nexus ML2 config to confdir + $cisco_ml2_mech_cisco_nexus_config_file = '/etc/neutron/conf.d/neutron-server/ml2_mech_cisco_nexus.ini' $opencontrail_plugin_package = 'neutron-plugin-contrail' $opencontrail_config_file = '/etc/neutron/plugins/opencontrail/ContrailPlugin.ini' @@ -106,9 +107,9 @@ class neutron::params { $sriov_nic_agent_service = 'neutron-plugin-sriov-agent' $sriov_nic_agent_package = 'neutron-plugin-sriov-agent' - $cisco_server_package = 'neutron-plugin-cisco' - $cisco_config_file = '/etc/neutron/plugins/cisco/cisco_plugins.ini' - $cisco_ml2_config_file = '/etc/neutron/plugins/ml2/ml2_conf_cisco.ini' + $cisco_server_package = 'neutron-plugin-cisco' + $cisco_config_file = '/etc/neutron/plugins/cisco/cisco_plugins.ini' + $cisco_ml2_mech_cisco_nexus_config_file = '/etc/neutron/plugins/ml2/ml2_mech_cisco_nexus.ini' $opencontrail_plugin_package = 'neutron-plugin-contrail' $opencontrail_config_file = '/etc/neutron/plugins/opencontrail/ContrailPlugin.ini' diff --git a/manifests/plugins/ml2/cisco.pp b/manifests/plugins/ml2/cisco.pp new file mode 100644 index 000000000..05ea71499 --- /dev/null +++ b/manifests/plugins/ml2/cisco.pp @@ -0,0 +1,31 @@ +# +# Install the Cisco plugins and generate the config file +# from parameters in the other classes. +# +# === Parameters +# +# [*package_ensure*] +# (optional) The intended state of the neutron-plugin-cisco +# package, i.e. any of the possible values of the 'ensure' +# property for a package resource type. +# Defaults to 'present' +# + +class neutron::plugins::ml2::cisco ( + $package_ensure = 'present' +) { + include ::neutron::params + require ::neutron::plugins::ml2 + + if($::osfamily != 'Redhat') { + # Drivers are only packaged for RedHat at this time + fail("Unsupported osfamily ${::osfamily}") + } + + ensure_resource('package', 'python-networking-cisco', + { + ensure => $package_ensure, + tag => 'openstack', + } + ) +} diff --git a/manifests/plugins/ml2/cisco/nexus.pp b/manifests/plugins/ml2/cisco/nexus.pp index 76b1adebf..e9a686060 100644 --- a/manifests/plugins/ml2/cisco/nexus.pp +++ b/manifests/plugins/ml2/cisco/nexus.pp @@ -5,42 +5,131 @@ # # === Parameters # -# [*neutron_config*] -# Neutron switch configuration for ml2_cisco_conf.ini +# [*nexus_config*] +# (required) Nexus switch configuration for ml2_cisco_conf.ini # Example nexus config format: # { 'switch_hostname' => {'username' => 'admin', # 'ssh_port' => 22, # 'password' => "password", # 'ip_address' => "172.18.117.28", +# 'nve_src_intf' => 1, +# 'physnet' => "physnet1", # 'servers' => { # 'control01' => "portchannel:20", # 'control02' => "portchannel:10" # }}} # +# [*managed_physical_network*] +# (required) The name of the physical_network managed via the Cisco +# Nexus Switch. This string value must be present in the ml2_conf.ini +# network_vlan_ranges variable. +# +# [*vlan_name_prefix*] +# (optional) A short prefix to prepend to the VLAN number when creating a +# VLAN interface. For example, if an interface is being created for +# VLAN 2001 it will be named 'q-2001' using the default prefix. +# The total length allowed for the prefix name and VLAN is 32 characters, +# the prefix will be truncated if the total length is greater than 32. +# Defaults to 'q-' +# +# [*svi_round_robin*] +# (optional) A flag to enable round robin scheduling of routers for SVI. +# Defaults to false +# +# [*provider_vlan_name_prefix*] +# (optional) A short prefix to prepend to the VLAN number when creating a +# provider VLAN interface. For example, if an interface is being created +# for provider VLAN 3003 it will be named 'p-3003' using the default prefix. +# The total length allowed for the prefix name and VLAN is 32 characters, +# the prefix will be truncated if the total length is greater than 32. +# Defaults to 'p-' +# +# [*persistent_switch_config*] +# (optional) To make Nexus device persistent by running the Nexus +# CLI 'copy run start' after applying successful configurations. +# (default) This flag defaults to False keep consistent with +# existing functionality. +# Defaults to false +# +# [*switch_heartbeat_time*] +# (optional) Time interval to check the state of the Nexus device. +# (default) This value defaults to 0 seconds which disables this +# functionality. When enabled, 30 seconds is suggested. +# Defaults to 0 +# +# [*switch_replay_count*] +# (optional) Number of times to attempt config replay with switch. +# This variable depends on switch_heartbeat_time being enabled. +# Defaults to 3 +# +# [*provider_vlan_auto_create*] +# (optional) A flag indicating whether OpenStack networking should manage the +# creation and removal of VLANs for provider networks on the Nexus +# switches. If the flag is set to False then OpenStack will not create or +# remove VLANs for provider networks, and the administrator needs to +# manage these interfaces manually or by external orchestration. +# Defaults to true +# +# [*provider_vlan_auto_trunk*] +# (optional) A flag indicating whether OpenStack networking should manage +# the adding and removing of provider VLANs from trunk ports on the Nexus +# switches. If the flag is set to False then OpenStack will not add or +# remove provider VLANs from trunk ports, and the administrator needs to +# manage these operations manually or by external orchestration. +# Defaults to true +# +# [*vxlan_global_config*] +# (optional) A flag indicating whether OpenStack networking should manage the +# creating and removing of the Nexus switch VXLAN global settings of 'feature +# nv overlay', 'feature vn-segment-vlan-based', 'interface nve 1' and the NVE +# subcommand 'source-interface loopback #'. If the flag is set to False +# (default) then OpenStack will not add or remove these VXLAN settings, and +# the administrator needs to manage these operations manually or by external +# orchestration. +# Defaults to true +# +# [*host_key_checks*] +# (optional) A flag indicating whether or not to enable strict host key checks +# when connecting to Nexus switches. +# Defaults to false +# class neutron::plugins::ml2::cisco::nexus ( - $nexus_config = undef, -) -{ + $nexus_config, + $managed_physical_network, + $vlan_name_prefix = 'q-', + $svi_round_robin = false, + $provider_vlan_name_prefix = 'p-', + $persistent_switch_config = false, + $switch_heartbeat_time = 0, + $switch_replay_count = 3, + $provider_vlan_auto_create = true, + $provider_vlan_auto_trunk = true, + $vxlan_global_config = true, + $host_key_checks = false +) { + include ::neutron::plugins::ml2::cisco - if !$nexus_config { - fail('No nexus config specified') + neutron_plugin_ml2 { + 'ml2_cisco/managed_physical_network' : value => $managed_physical_network; + 'ml2_cisco/vlan_name_prefix' : value => $vlan_name_prefix; + 'ml2_cisco/svi_round_robin' : value => $svi_round_robin; + 'ml2_cisco/provider_vlan_name_prefix' : value => $provider_vlan_name_prefix; + 'ml2_cisco/persistent_switch_config' : value => $persistent_switch_config; + 'ml2_cisco/switch_heartbeat_time' : value => $switch_heartbeat_time; + 'ml2_cisco/switch_replay_count' : value => $switch_replay_count; + 'ml2_cisco/provider_vlan_auto_create' : value => $provider_vlan_auto_create; + 'ml2_cisco/provider_vlan_auto_trunk' : value => $provider_vlan_auto_trunk; + 'ml2_cisco/vxlan_global_config' : value => $vxlan_global_config; + 'ml2_cisco/host_key_checks' : value => $host_key_checks; } - # For Ubuntu: This package is not available upstream - # Please use the source from: - # https://launchpad.net/~cisco-openstack/+archive/python-ncclient - # and install it manually - package { 'python-ncclient': - ensure => installed, - tag => 'openstack', - } ~> Service['neutron-server'] - - Neutron_plugin_ml2<||> -> - file { $::neutron::params::cisco_ml2_config_file: + file { 'nexus_config': + path => $::neutron::params::cisco_ml2_mech_cisco_nexus_config_file, owner => 'root', - group => 'root', - content => template('neutron/ml2_conf_cisco.ini.erb'), + group => 'neutron', + mode => '0644', + content => template('neutron/ml2_mech_cisco_nexus_conf.erb'), } ~> Service['neutron-server'] create_resources(neutron::plugins::ml2::cisco::nexus_creds, $nexus_config) diff --git a/manifests/plugins/ml2/cisco/nexus1000v.pp b/manifests/plugins/ml2/cisco/nexus1000v.pp index 0d05fc29b..aeac6c59f 100644 --- a/manifests/plugins/ml2/cisco/nexus1000v.pp +++ b/manifests/plugins/ml2/cisco/nexus1000v.pp @@ -87,16 +87,7 @@ class neutron::plugins::ml2::cisco::nexus1000v ( $enable_vif_type_n1kv = 'False', ) { - if($::osfamily != 'Redhat') { - # Current support exists for Redhat family. - # Support for Debian will be added in the future. - fail("Unsupported osfamily ${::osfamily}") - } - - package { 'python-networking-cisco': - require => Package['openstack-neutron'], - tag => 'openstack', - } + include ::neutron::plugins::ml2::cisco $extension_drivers = 'cisco_n1kv_ext' neutron_plugin_ml2 { diff --git a/manifests/plugins/ml2/cisco/nexus_creds.pp b/manifests/plugins/ml2/cisco/nexus_creds.pp index 16c262cb0..4b3cc0cbb 100644 --- a/manifests/plugins/ml2/cisco/nexus_creds.pp +++ b/manifests/plugins/ml2/cisco/nexus_creds.pp @@ -1,5 +1,7 @@ # -# Configure the Mech Driver for cisco neutron plugin +# Defined type to configure the Cisco Nexus Switch Credentials +# for use by the ML2 Mech Driver for Cisco Nexus Switches. +# # More info available here: # https://wiki.openstack.org/wiki/Neutron/ML2/MechCiscoNexus # @@ -7,25 +9,110 @@ # neutron::plugins::ml2::cisco::nexus_creds used by # neutron::plugins::ml2::cisco::nexus # +# === Parameters +# +# [*username*] +# (required) The username for logging into the switch to manage it. +# +# [*password*] +# (required) The password for logging into the switch to manage it. +# +# [*servers*] +# (required) A hash of server names (key) mapped to the switch's +# interfaces (value). For each host connected to a port on the +# switch, specify the hostname and the Nexus physical port/s +# (interface/s) it is connected to. The values in the hash can +# be a comma separated list of interfaces mapped to the server. +# +# Hash Format: +# +# { +# => ",,<... interfaceID_N>" +# } +# +# Interface ID format options: +# ":" +# Valid intf_type's are 'ethernet' and 'port-channel'. +# The default setting for is 'ethernet' and need not be +# added to this setting. +# +# Example: +# { +# 'control1' => 'ethernet:1/1', +# 'control2' => 'ethernet:1/2', +# 'compute1' => '1/3,1/4' +# } +# +# [*ip_address*] +# (required) The IP address of the switch. +# +# [*ssh_port*] +# (required) The SSH port to use when connecting to the switch. +# +# [*nve_src_intf*] +# (optional) Only valid if VXLAN overlay is configured and +# vxlan_global_config is set to True. +# +# The NVE source interface is a loopback interface that is configured on +# the switch with valid /32 IP address. This /32 IP address must be known +# by the transient devices in the transport network and the remote VTEPs. +# This is accomplished by advertising it through a dynamic routing protocol +# in the transport network. (NB: If no nve_src_intf is defined then a +# default setting of 0 (creates "loopback0") will be used.) +# +# Defaults to undef. +# +# [*physnet*] +# (optional) Only valid if VXLAN overlay is configured. +# The physical network name defined in the network_vlan_ranges variable +# (defined under the ml2_type_vlan section) that this switch is controlling. +# The configured 'physnet' is the physical network domain that is connected +# to this switch. The vlan ranges defined in network_vlan_ranges for a +# a physical network are allocated dynamically and are unique per physical +# network. These dynamic vlans may be reused across physical networks. +# +# Defaults to undef. define neutron::plugins::ml2::cisco::nexus_creds( $username, $password, $servers, $ip_address, - $ssh_port + $ssh_port, + $nve_src_intf = undef, + $physnet = undef, ) { - - file {'/var/lib/neutron/.ssh': - ensure => directory, - owner => 'neutron', - require => Package['neutron-server'] + # Ensure Neutron server is installed before configuring ssh keys + if ($::neutron::params::server_package) { + Package['neutron-server'] -> File['/var/lib/neutron/.ssh'] + Package['neutron-server'] -> Exec["nexus_creds_${name}"] + } else { + Package['neutron'] -> File['/var/lib/neutron/.ssh'] + Package['neutron'] -> Exec["nexus_creds_${name}"] } - exec {'nexus_creds': - unless => "/bin/cat /var/lib/neutron/.ssh/known_hosts | /bin/grep ${username}", + ensure_resource('file', '/var/lib/neutron/.ssh', + { + ensure => directory, + owner => 'neutron', + } + ) + + $check_known_hosts = "/bin/cat /var/lib/neutron/.ssh/known_hosts | /bin/grep ${ip_address}" + + # Test to make sure switch is reachable before ssh-keyscan. + # - ssh-keyscan timeouts fail silently so use ping to + # report connectivity failures. + exec {"ping_test_${name}": + unless => $check_known_hosts, + command => "/usr/bin/ping -c 1 ${ip_address}", + user => 'neutron' + } + + exec {"nexus_creds_${name}": + unless => $check_known_hosts, command => "/usr/bin/ssh-keyscan -t rsa ${ip_address} >> /var/lib/neutron/.ssh/known_hosts", user => 'neutron', - require => [Package['neutron-server'], File['/var/lib/neutron/.ssh']] + require => [Exec["ping_test_${name}"], File['/var/lib/neutron/.ssh']] } } diff --git a/manifests/plugins/ml2/cisco/type_nexus_vxlan.pp b/manifests/plugins/ml2/cisco/type_nexus_vxlan.pp new file mode 100644 index 000000000..7e69bfbec --- /dev/null +++ b/manifests/plugins/ml2/cisco/type_nexus_vxlan.pp @@ -0,0 +1,35 @@ +# +# Configure the Nexus VXLAN Type Driver +# More info available here: +# http://docwiki.cisco.com/wiki/OpenStack/ML2NexusMechanismDriver +# +# === Parameters +# +# [*vni_ranges*] +# (required) +# Comma-separated list of : tuples enumerating +# ranges of VXLAN Network IDs that are available for tenant network +# allocation. +# +# [*mcast_ranges*] +# (required) +# Multicast groups for the VXLAN interface. When configured, will +# enable sending all broadcast traffic to this multicast group. +# Comma separated list of min:max ranges of multicast IP's. +# NOTE: must be a valid multicast IP, invalid IP's will be discarded +# Example: +# 224.0.0.1:224.0.0.3,224.0.1.1:224.0.1.3 +# + +class neutron::plugins::ml2::cisco::type_nexus_vxlan ( + $vni_ranges, + $mcast_ranges, +) { + include ::neutron::plugins::ml2::cisco + + neutron_plugin_ml2 { + 'ml2_type_nexus_vxlan/vni_ranges' : value => $vni_ranges; + 'ml2_type_nexus_vxlan/mcast_ranges' : value => $mcast_ranges; + } +} + diff --git a/manifests/plugins/ml2/cisco/ucsm.pp b/manifests/plugins/ml2/cisco/ucsm.pp new file mode 100644 index 000000000..0a3ed131b --- /dev/null +++ b/manifests/plugins/ml2/cisco/ucsm.pp @@ -0,0 +1,48 @@ +# +# Configure the Mech Driver for Cisco UCSM plugin +# More info available here: +# http://docwiki.cisco.com/wiki/UCS_Mechanism_Driver_for_ML2_Plugin:_Kilo +# +# === Parameters +# +# [*ucsm_ip*] +# (required) IP address of the Cisco UCS Manager +# +# [*ucsm_username*] +# (required) Username to connect to the UCS Manager +# +# [*ucsm_password*] +# (required) Password to connect to the UCS Manager +# +# [*ucsm_host_list*] +# (required) +# Hostname to Service profile mapping for UCSM-controlled compute hosts +# Example: +# Hostname1:Serviceprofile1, Hostname2:Serviceprofile2 +# +# [*supported_pci_devs*] +# (optional) SR-IOV and VM-FEX vendors supported by this plugin +# xxxx:yyyy represents vendor_id:product_id +# Defaults to undef +# Example: +# [ '2222:3333', '4444:5555' ] +# + +class neutron::plugins::ml2::cisco::ucsm ( + $ucsm_ip, + $ucsm_username, + $ucsm_password, + $ucsm_host_list, + $supported_pci_devs = undef, +) { + include ::neutron::plugins::ml2::cisco + + neutron_plugin_ml2 { + 'ml2_cisco_ucsm/ucsm_ip' : value => $ucsm_ip; + 'ml2_cisco_ucsm/ucsm_username' : value => $ucsm_username; + 'ml2_cisco_ucsm/ucsm_password' : value => $ucsm_password; + 'ml2_cisco_ucsm/ucsm_host_list' : value => $ucsm_host_list; + 'ml2_cisco_ucsm/supported_pci_devs' : value => $supported_pci_devs; + } +} + diff --git a/manifests/plugins/ml2/type_driver.pp b/manifests/plugins/ml2/type_driver.pp index af50157a9..892a3b66a 100644 --- a/manifests/plugins/ml2/type_driver.pp +++ b/manifests/plugins/ml2/type_driver.pp @@ -83,6 +83,9 @@ define neutron::plugins::ml2::type_driver ( elsif ($name == 'local') { warning('local type_driver is useful only for single-box, because it provides no connectivity between hosts') } + elsif ($name == 'nexus_vxlan') { + # Nexus_vxlan type driver has its own class separate from this one + } else { # detect an invalid type_drivers value fail('type_driver unknown.') diff --git a/spec/classes/neutron_plugins_cisco_ml2_spec.rb b/spec/classes/neutron_plugins_cisco_ml2_spec.rb deleted file mode 100644 index d23945d6b..000000000 --- a/spec/classes/neutron_plugins_cisco_ml2_spec.rb +++ /dev/null @@ -1,117 +0,0 @@ -# -# Unit tests for neutron::plugins::ml2 class -# - -require 'spec_helper' - -describe 'neutron::plugins::ml2::cisco::nexus' do - - let :pre_condition do - "class { 'neutron::server': auth_password => 'password'} - class { 'neutron': - rabbit_password => 'passw0rd', - core_plugin => 'neutron.plugins.ml2.plugin.Ml2Plugin' }" - end - - let :default_params do - { - :nexus_config => nil - } - end - - let :params do - {} - end - - let :facts do - { :operatingsystem => 'default', - :operatingsystemrelease => 'default', - :osfamily => 'Debian' - } - end - - context 'fail when missing nexus_config' do - it_raises 'a Puppet::Error', /No nexus config specified/ - end - - context 'when using cisco' do - let (:nexus_config) do - { 'cvf2leaff2' => {'username' => 'prad', - "ssh_port" => 22, - "password" => "password", - "ip_address" => "172.18.117.28", - "servers" => { - "control02" => "portchannel:20", - "control01" => "portchannel:10" - } - } - } - end - - before :each do - params.merge!(:nexus_config => nexus_config ) - end - - it 'installs ncclient package' do - is_expected.to contain_package('python-ncclient').with( - :ensure => 'installed', - :tag => 'openstack' - ) - end - - end - -end - - -describe 'neutron::plugins::ml2::cisco::nexus1000v' do - - context 'verify default n1kv params in plugin.ini' do - - let :facts do - { :operatingsystem => 'RedHat', - :operatingsystemrelease => '7', - :osfamily => 'RedHat' - } - end - - let :params do - { - :n1kv_vsm_ip => '9.0.0.1', - :n1kv_vsm_username => 'user1', - :n1kv_vsm_password => 'pasSw0rd', - :default_policy_profile => 'test-pp', - :default_vlan_network_profile => 'test-vlan-np', - :default_vxlan_network_profile => 'test-vxlan-np', - :poll_duration => '120', - :http_pool_size => '6', - :http_timeout => '60', - :sync_interval => '30', - :max_vsm_retries => '3', - :restrict_policy_profiles => 'False', - :enable_vif_type_n1kv => 'True', - } - end - let :ml2_params do - { - :extension_drivers => 'cisco_n1kv_ext', - } - end - it do - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/n1kv_vsm_ips').with_value(params[:n1kv_vsm_ip]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/username').with_value(params[:n1kv_vsm_username]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/password').with_value(params[:n1kv_vsm_password]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/default_policy_profile').with_value(params[:default_policy_profile]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/default_vlan_network_profile').with_value(params[:default_vlan_network_profile]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/default_vxlan_network_profile').with_value(params[:default_vxlan_network_profile]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/poll_duration').with_value(params[:poll_duration]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/http_pool_size').with_value(params[:http_pool_size]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/http_timeout').with_value(params[:http_timeout]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/sync_interval').with_value(params[:sync_interval]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/max_vsm_retries').with_value(params[:max_vsm_retries]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/restrict_policy_profiles').with_value(params[:restrict_policy_profiles]) - is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/enable_vif_type_n1kv').with_value(params[:enable_vif_type_n1kv]) - is_expected.to contain_neutron_plugin_ml2('ml2/extension_drivers').with_value(ml2_params[:extension_drivers]) - end - end -end diff --git a/spec/classes/neutron_plugins_ml2_cisco_nexus_spec.rb b/spec/classes/neutron_plugins_ml2_cisco_nexus_spec.rb new file mode 100644 index 000000000..cab9d7acb --- /dev/null +++ b/spec/classes/neutron_plugins_ml2_cisco_nexus_spec.rb @@ -0,0 +1,105 @@ +# +# Unit tests for neutron::plugins::ml2::cisco::nexus class +# + +require 'spec_helper' + +describe 'neutron::plugins::ml2::cisco::nexus' do + + let :pre_condition do + "class { 'neutron::server': auth_password => 'password'} + class { 'neutron': + rabbit_password => 'passw0rd', + core_plugin => 'neutron.plugins.ml2.plugin.Ml2Plugin' }" + end + + let :default_params do + { + :nexus_config => { + 'cvf2leaff2' => { + 'username' => 'prad', + "ssh_port" => 22, + "password" => "password", + "ip_address" => "172.18.117.28", + "nve_src_intf" => 1, + "physnet" => "physnet1", + "servers" => { + "control02" => "portchannel:20", + "control01" => "portchannel:10" + } + } + }, + :managed_physical_network => 'physnet1', + :vlan_name_prefix => 'q-', + :svi_round_robin => false, + :provider_vlan_name_prefix => 'p-', + :persistent_switch_config => false, + :switch_heartbeat_time => 0, + :switch_replay_count => 3, + :provider_vlan_auto_create => true, + :provider_vlan_auto_trunk => true, + :vxlan_global_config => true, + :host_key_checks => false + } + end + + let :params do + {} + end + + let :default_facts do + { :operatingsystem => 'default', + :operatingsystemrelease => 'default', + :concat_basedir => '/', + } + end + + shared_examples_for 'neutron cisco ml2 nexus plugin' do + + before do + params.merge!(default_params) + end + + it { is_expected.to contain_class('neutron::params') } + + it do + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/managed_physical_network').with_value(params[:managed_physical_network]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/vlan_name_prefix').with_value(params[:vlan_name_prefix]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/svi_round_robin').with_value(params[:svi_round_robin]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/provider_vlan_name_prefix').with_value(params[:provider_vlan_name_prefix]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/persistent_switch_config').with_value(params[:persistent_switch_config]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/switch_heartbeat_time').with_value(params[:switch_heartbeat_time]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/switch_replay_count').with_value(params[:switch_replay_count]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/provider_vlan_auto_create').with_value(params[:provider_vlan_auto_create]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/provider_vlan_auto_trunk').with_value(params[:provider_vlan_auto_trunk]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/vxlan_global_config').with_value(params[:vxlan_global_config]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco/host_key_checks').with_value(params[:host_key_checks]) + end + + it { should contain_file('nexus_config').with({ + :path => platform_params[:cisco_ml2_config_file]}) } + + it { + # Stored as an array of arrays with the first element consisting of the name and + # the second element consisting of the config hash + params[:nexus_config].each do |switch_config| + should contain_neutron__plugins__ml2__cisco__nexus_creds(switch_config.first) + end + } + + end + + begin + context 'on RedHat platforms' do + let :facts do + default_facts.merge({:osfamily => 'RedHat'}) + end + + let :platform_params do + { :cisco_ml2_config_file => '/etc/neutron/conf.d/neutron-server/ml2_mech_cisco_nexus.ini' } + end + + it_configures 'neutron cisco ml2 nexus plugin' + end + end +end diff --git a/spec/classes/neutron_plugins_ml2_cisco_spec.rb b/spec/classes/neutron_plugins_ml2_cisco_spec.rb new file mode 100644 index 000000000..d6cdfd78c --- /dev/null +++ b/spec/classes/neutron_plugins_ml2_cisco_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe 'neutron::plugins::ml2::cisco' do + + let :pre_condition do + "class { 'neutron::server': auth_password => 'password'} + class { 'neutron': + rabbit_password => 'passw0rd', + core_plugin => 'neutron.plugins.ml2.plugin.Ml2Plugin' }" + end + + let :default_params do + { + :package_ensure => 'present' + } + end + + let :params do + {} + end + + let :default_facts do + { + :operatingsystem => 'default', + :operatingsystemrelease => 'default', + :concat_basedir => '/', + } + end + + + shared_examples_for 'neutron plugin cisco ml2' do + before do + params.merge!(default_params) + end + + it { is_expected.to contain_class('neutron::params') } + + it 'should have' do + is_expected.to contain_package('python-networking-cisco').with( + :ensure => params[:package_ensure], + :tag => 'openstack' + ) + end + end + + begin + context 'on RedHat platforms' do + let :facts do + default_facts.merge({:osfamily => 'RedHat'}) + end + + it_configures 'neutron plugin cisco ml2' + end + end +end diff --git a/spec/classes/neutron_plugins_ml2_cisco_type_nexus_vxlan_spec.rb b/spec/classes/neutron_plugins_ml2_cisco_type_nexus_vxlan_spec.rb new file mode 100644 index 000000000..affac4ba1 --- /dev/null +++ b/spec/classes/neutron_plugins_ml2_cisco_type_nexus_vxlan_spec.rb @@ -0,0 +1,58 @@ +# +# Unit tests for neutron::plugins::ml2::cisco::type_nexus_vxlan class +# + +require 'spec_helper' + +describe 'neutron::plugins::ml2::cisco::type_nexus_vxlan' do + + let :pre_condition do + "class { 'neutron::server': auth_password => 'password'} + class { 'neutron': + rabbit_password => 'passw0rd', + core_plugin => 'neutron.plugins.ml2.plugin.Ml2Plugin' }" + end + + let :default_params do + { + :vni_ranges => '20000:22000', + :mcast_ranges => '224.0.0.1:224.0.0.3,224.0.1.1:224.0.1.3' + } + end + + let :params do + {} + end + + let :default_facts do + { :operatingsystem => 'default', + :operatingsystemrelease => 'default', + :concat_basedir => '/', + } + end + + shared_examples_for 'neutron cisco ml2 type nexus vxlan plugin' do + + before do + params.merge!(default_params) + end + + it { is_expected.to contain_class('neutron::params') } + + it do + is_expected.to contain_neutron_plugin_ml2('ml2_type_nexus_vxlan/vni_ranges').with_value(params[:vni_ranges]) + is_expected.to contain_neutron_plugin_ml2('ml2_type_nexus_vxlan/mcast_ranges').with_value(params[:mcast_ranges]) + end + + end + + begin + context 'on RedHat platforms' do + let :facts do + default_facts.merge({:osfamily => 'RedHat'}) + end + + it_configures 'neutron cisco ml2 type nexus vxlan plugin' + end + end +end diff --git a/spec/classes/neutron_plugins_ml2_cisco_ucsm_spec.rb b/spec/classes/neutron_plugins_ml2_cisco_ucsm_spec.rb new file mode 100644 index 000000000..26c211072 --- /dev/null +++ b/spec/classes/neutron_plugins_ml2_cisco_ucsm_spec.rb @@ -0,0 +1,64 @@ +# +# Unit tests for neutron::plugins::ml2::cisco::ucsm class +# + +require 'spec_helper' + +describe 'neutron::plugins::ml2::cisco::ucsm' do + + let :pre_condition do + "class { 'neutron::server': auth_password => 'password'} + class { 'neutron': + rabbit_password => 'passw0rd', + core_plugin => 'neutron.plugins.ml2.plugin.Ml2Plugin' }" + end + + let :default_params do + { + :ucsm_ip => '1.1.1.1', + :ucsm_username => 'admin', + :ucsm_password => 'password', + :ucsm_host_list => 'host1:profile1, host2:profile2', + :supported_pci_devs => [ '2222:3333', '4444:5555' ] + } + end + + let :params do + {} + end + + let :default_facts do + { :operatingsystem => 'default', + :operatingsystemrelease => 'default', + :concat_basedir => '/', + } + end + + shared_examples_for 'neutron cisco ml2 ucsm plugin' do + + before do + params.merge!(default_params) + end + + it { is_expected.to contain_class('neutron::params') } + + it do + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_ucsm/ucsm_ip').with_value(params[:ucsm_ip]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_ucsm/ucsm_username').with_value(params[:ucsm_username]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_ucsm/ucsm_password').with_value(params[:ucsm_password]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_ucsm/ucsm_host_list').with_value(params[:ucsm_host_list]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_ucsm/supported_pci_devs').with_value(params[:supported_pci_devs]) + end + + end + + begin + context 'on RedHat platforms' do + let :facts do + default_facts.merge({:osfamily => 'RedHat'}) + end + + it_configures 'neutron cisco ml2 ucsm plugin' + end + end +end diff --git a/templates/ml2_conf_cisco.ini.erb b/templates/ml2_mech_cisco_nexus_conf.erb similarity index 51% rename from templates/ml2_conf_cisco.ini.erb rename to templates/ml2_mech_cisco_nexus_conf.erb index 0eba9aae4..b9209274b 100644 --- a/templates/ml2_conf_cisco.ini.erb +++ b/templates/ml2_mech_cisco_nexus_conf.erb @@ -1,23 +1,3 @@ -[ml2_cisco] - -# (StrOpt) A short prefix to prepend to the VLAN number when creating a -# VLAN interface. For example, if an interface is being created for -# VLAN 2001 it will be named 'q-2001' using the default prefix. -# -# vlan_name_prefix = q- -# Example: vlan_name_prefix = vnet- - -# (BoolOpt) A flag to enable round robin scheduling of routers for SVI. -# svi_round_robin = False - -# -# (StrOpt) The name of the physical_network managed via the Cisco Nexus Switch. -# This string value must be present in the ml2_conf.ini network_vlan_ranges -# variable. -# -# managed_physical_network = -# Example: managed_physical_network = physnet1 - # Cisco Nexus Switch configurations. # Each switch to be managed by Openstack Neutron must be configured here. # @@ -27,6 +7,8 @@ # ssh_port= (2) # username= (3) # password= (4) +# nve_src_intf= (5) +# physnet= (6) # # (1) For each host connected to a port on the switch, specify the hostname # and the Nexus physical port (interface) it is connected to. @@ -37,6 +19,21 @@ # port number 22 unless the switch has been configured otherwise. # (3) The username for logging into the switch to manage it. # (4) The password for logging into the switch to manage it. +# (5) Only valid if VXLAN overlay is configured and vxlan_global_config is +# set to True. +# The NVE source interface is a loopback interface that is configured on +# the switch with valid /32 IP address. This /32 IP address must be known +# by the transient devices in the transport network and the remote VTEPs. +# This is accomplished by advertising it through a dynamic routing protocol +# in the transport network. (NB: If no nve_src_intf is defined then a +# default setting of 0 (creates "loopback0") will be used.) +# (6) Only valid if VXLAN overlay is configured. +# The physical network name defined in the network_vlan_ranges variable +# (defined under the ml2_type_vlan section) that this switch is controlling. +# The configured 'physnet' is the physical network domain that is connected +# to this switch. The vlan ranges defined in network_vlan_ranges for a +# a physical network are allocated dynamically and are unique per physical +# network. These dynamic vlans may be reused across physical networks. # # Example: # [ml2_mech_cisco_nexus:1.1.1.1] @@ -46,14 +43,17 @@ # ssh_port=22 # username=admin # password=mySecretPassword +# nve_src_intf=1 +# physnet=physnet1 <% @nexus_config.each do |switch_hostname, switch_data| %> [ML2_MECH_CISCO_NEXUS:<%= switch_data['ip_address'] %>] -<%- switch_data['servers'].each do|host_name, port| -%> +<%- switch_data['servers'].each do |host_name, port| -%> <%=host_name-%>=<%= port %> <%- end -%> ssh_port=<%= switch_data['ssh_port'] %> username=<%= switch_data['username'] %> password=<%= switch_data['password'] %> +nve_src_intf=<%= switch_data['nve_src_intf'] %> +physnet=<%= switch_data['physnet'] %> <% end %> -