Open vSwitch integration with host and configuration framework
Integrates the latest Open vSwitch with DPDK into the host management and configuration framework and configures the default system vswitch type to be ovs-dpdk. Change-Id: If7ef2975e4b90ce84d170051f332f778a867a873 Signed-off-by: Matt Peters <matt.peters@windriver.com>
This commit is contained in:
parent
69365bb834
commit
9fafe08b65
@ -710,7 +710,7 @@ class ConfigValidator(object):
|
||||
self.vswitch_type = self.conf.get('NETWORK',
|
||||
'VSWITCH_TYPE').upper()
|
||||
else:
|
||||
self.vswitch_type = 'AVS'
|
||||
self.vswitch_type = 'OVS-DPDK'
|
||||
|
||||
if self.vswitch_type == 'NUAGE_VRS':
|
||||
metadata_proxy_shared_secret = self.conf.get(
|
||||
@ -755,10 +755,10 @@ class ConfigValidator(object):
|
||||
raise ConfigFail(
|
||||
"The Region Names must be unique.")
|
||||
# validate VSWITCH_TYPE configuration
|
||||
if self.vswitch_type == 'AVS':
|
||||
if self.vswitch_type == 'OVS-DPDK':
|
||||
if self.conf.has_option('SHARED_SERVICES', 'NEUTRON_SERVICE_NAME'):
|
||||
raise ConfigFail(
|
||||
"When VSWITCH_TYPE is AVS, NEUTRON service must "
|
||||
"When VSWITCH_TYPE is OVS-DPDK, NEUTRON service must "
|
||||
"only be configured in REGION_2_SERVICES.")
|
||||
neutron_group = 'REGION_2_SERVICES'
|
||||
neutron_region_name = region_2_name
|
||||
|
@ -443,23 +443,7 @@ class ConfigAssistant():
|
||||
# HTTPS
|
||||
self.enable_https = False
|
||||
# Network config
|
||||
self.vswitch_type = "avs"
|
||||
self.neutron_l2_plugin = "ml2"
|
||||
self.neutron_l2_agent = "vswitch"
|
||||
self.neutron_l3_ext_bridge = 'provider'
|
||||
self.neutron_mechanism_drivers = "vswitch,sriovnicswitch,l2population"
|
||||
self.neutron_sriov_agent_required = "y"
|
||||
self.neutron_type_drivers = "managed_flat,managed_vlan,managed_vxlan"
|
||||
self.neutron_network_types = "vlan,vxlan"
|
||||
self.neutron_host_driver = \
|
||||
"neutron.plugins.wrs.drivers.host.DefaultHostDriver"
|
||||
self.neutron_fm_driver = \
|
||||
"neutron.plugins.wrs.drivers.fm.DefaultFmDriver"
|
||||
self.neutron_network_scheduler = \
|
||||
"neutron.scheduler.dhcp_host_agent_scheduler.HostBasedScheduler"
|
||||
self.neutron_router_scheduler = \
|
||||
"neutron.scheduler.l3_host_agent_scheduler.HostBasedScheduler"
|
||||
self.metadata_proxy_shared_secret = ""
|
||||
self.vswitch_type = "ovs-dpdk"
|
||||
|
||||
# Authentication config
|
||||
self.admin_username = "admin"
|
||||
@ -2622,48 +2606,6 @@ class ConfigAssistant():
|
||||
# If any of the network options are missing, use defaults.
|
||||
if config.has_option('cNETWORK', 'VSWITCH_TYPE'):
|
||||
self.vswitch_type = config.get('cNETWORK', 'VSWITCH_TYPE')
|
||||
if config.has_option('cNETWORK', 'NEUTRON_L2_PLUGIN'):
|
||||
self.neutron_l2_plugin = config.get(
|
||||
'cNETWORK', 'NEUTRON_L2_PLUGIN')
|
||||
if config.has_option('cNETWORK', 'NEUTRON_L2_AGENT'):
|
||||
self.neutron_l2_agent = config.get(
|
||||
'cNETWORK', 'NEUTRON_L2_AGENT')
|
||||
if config.has_option('cNETWORK', 'NEUTRON_L3_EXT_BRIDGE'):
|
||||
self.neutron_l3_ext_bridge = config.get(
|
||||
'cNETWORK', 'NEUTRON_L3_EXT_BRIDGE')
|
||||
if config.has_option('cNETWORK',
|
||||
'NEUTRON_ML2_MECHANISM_DRIVERS'):
|
||||
self.neutron_mechanism_drivers = config.get(
|
||||
'cNETWORK', 'NEUTRON_ML2_MECHANISM_DRIVERS')
|
||||
if config.has_option('cNETWORK',
|
||||
'NEUTRON_ML2_TYPE_DRIVERS'):
|
||||
self.neutron_type_drivers = config.get(
|
||||
'cNETWORK', 'NEUTRON_ML2_TYPE_DRIVERS')
|
||||
if config.has_option('cNETWORK',
|
||||
'NEUTRON_ML2_TENANT_NETWORK_TYPES'):
|
||||
self.neutron_network_types = config.get(
|
||||
'cNETWORK', 'NEUTRON_ML2_TENANT_NETWORK_TYPES')
|
||||
if config.has_option('cNETWORK',
|
||||
'NEUTRON_ML2_SRIOV_AGENT_REQUIRED'):
|
||||
self.neutron_sriov_agent_required = config.get(
|
||||
'cNETWORK', 'NEUTRON_ML2_SRIOV_AGENT_REQUIRED')
|
||||
if config.has_option('cNETWORK', 'NEUTRON_HOST_DRIVER'):
|
||||
self.neutron_host_driver = config.get(
|
||||
'cNETWORK', 'NEUTRON_HOST_DRIVER')
|
||||
if config.has_option('cNETWORK', 'NEUTRON_FM_DRIVER'):
|
||||
self.neutron_fm_driver = config.get(
|
||||
'cNETWORK', 'NEUTRON_FM_DRIVER')
|
||||
if config.has_option('cNETWORK',
|
||||
'NEUTRON_NETWORK_SCHEDULER'):
|
||||
self.neutron_network_scheduler = config.get(
|
||||
'cNETWORK', 'NEUTRON_NETWORK_SCHEDULER')
|
||||
if config.has_option('cNETWORK',
|
||||
'NEUTRON_ROUTER_SCHEDULER'):
|
||||
self.neutron_router_scheduler = config.get(
|
||||
'cNETWORK', 'NEUTRON_ROUTER_SCHEDULER')
|
||||
if self.vswitch_type == "nuage_vrs":
|
||||
self.metadata_proxy_shared_secret = config.get(
|
||||
'cNETWORK', 'METADATA_PROXY_SHARED_SECRET')
|
||||
|
||||
# Authentication configuration
|
||||
if config.has_section('cAUTHENTICATION'):
|
||||
@ -3289,31 +3231,6 @@ class ConfigAssistant():
|
||||
f.write("\n[cNETWORK]")
|
||||
f.write("\n# Data Network Configuration\n")
|
||||
f.write("VSWITCH_TYPE=%s\n" % self.vswitch_type)
|
||||
f.write("NEUTRON_L2_PLUGIN=" +
|
||||
str(self.neutron_l2_plugin) + "\n")
|
||||
f.write("NEUTRON_L2_AGENT=" +
|
||||
str(self.neutron_l2_agent) + "\n")
|
||||
f.write("NEUTRON_L3_EXT_BRIDGE=" +
|
||||
str(self.neutron_l3_ext_bridge) + "\n")
|
||||
f.write("NEUTRON_ML2_MECHANISM_DRIVERS=" +
|
||||
str(self.neutron_mechanism_drivers) + "\n")
|
||||
f.write("NEUTRON_ML2_TYPE_DRIVERS=" +
|
||||
str(self.neutron_type_drivers) + "\n")
|
||||
f.write("NEUTRON_ML2_TENANT_NETWORK_TYPES=" +
|
||||
str(self.neutron_network_types) + "\n")
|
||||
f.write("NEUTRON_ML2_SRIOV_AGENT_REQUIRED=" +
|
||||
str(self.neutron_sriov_agent_required) + "\n")
|
||||
f.write("NEUTRON_HOST_DRIVER=" +
|
||||
str(self.neutron_host_driver) + "\n")
|
||||
f.write("NEUTRON_FM_DRIVER=" +
|
||||
str(self.neutron_fm_driver) + "\n")
|
||||
f.write("NEUTRON_NETWORK_SCHEDULER=" +
|
||||
str(self.neutron_network_scheduler) + "\n")
|
||||
f.write("NEUTRON_ROUTER_SCHEDULER=" +
|
||||
str(self.neutron_router_scheduler) + "\n")
|
||||
if self.vswitch_type == "nuage_vrs":
|
||||
f.write("METADATA_PROXY_SHARED_SECRET=" +
|
||||
str(self.metadata_proxy_shared_secret) + "\n")
|
||||
|
||||
# Security configuration
|
||||
f.write("\n[cSECURITY]")
|
||||
|
@ -54,7 +54,7 @@ EXTERNAL_OAM_0_ADDRESS = 10.10.10.3
|
||||
EXTERNAL_OAM_1_ADDRESS = 10.10.10.4
|
||||
|
||||
[cNETWORK]
|
||||
VSWITCH_TYPE = avs
|
||||
VSWITCH_TYPE = ovs-dpdk
|
||||
|
||||
[cREGION]
|
||||
REGION_CONFIG = True
|
||||
|
@ -54,7 +54,7 @@ EXTERNAL_OAM_0_ADDRESS = 10.10.10.3
|
||||
EXTERNAL_OAM_1_ADDRESS = 10.10.10.4
|
||||
|
||||
[cNETWORK]
|
||||
VSWITCH_TYPE = avs
|
||||
VSWITCH_TYPE = ovs-dpdk
|
||||
|
||||
[cREGION]
|
||||
REGION_CONFIG = True
|
||||
|
@ -56,18 +56,7 @@ EXTERNAL_OAM_1_ADDRESS=10.10.10.4
|
||||
|
||||
[cNETWORK]
|
||||
# Data Network Configuration
|
||||
VSWITCH_TYPE=avs
|
||||
NEUTRON_L2_PLUGIN=ml2
|
||||
NEUTRON_L2_AGENT=vswitch
|
||||
NEUTRON_L3_EXT_BRIDGE=provider
|
||||
NEUTRON_ML2_MECHANISM_DRIVERS=vswitch,sriovnicswitch
|
||||
NEUTRON_ML2_TYPE_DRIVERS=managed_flat,managed_vlan,managed_vxlan
|
||||
NEUTRON_ML2_TENANT_NETWORK_TYPES=vlan,vxlan
|
||||
NEUTRON_ML2_SRIOV_AGENT_REQUIRED=False
|
||||
NEUTRON_HOST_DRIVER=neutron.plugins.wrs.drivers.host.DefaultHostDriver
|
||||
NEUTRON_FM_DRIVER=neutron.plugins.wrs.drivers.fm.DefaultFmDriver
|
||||
NEUTRON_NETWORK_SCHEDULER=neutron.scheduler.dhcp_host_agent_scheduler.HostChanceScheduler
|
||||
NEUTRON_ROUTER_SCHEDULER=neutron.scheduler.l3_host_agent_scheduler.HostChanceScheduler
|
||||
VSWITCH_TYPE=ovs-dpdk
|
||||
|
||||
[cSECURITY]
|
||||
[cREGION]
|
||||
|
@ -62,18 +62,7 @@ EXTERNAL_OAM_1_ADDRESS=10.10.10.4
|
||||
|
||||
[cNETWORK]
|
||||
# Data Network Configuration
|
||||
VSWITCH_TYPE=avs
|
||||
NEUTRON_L2_PLUGIN=ml2
|
||||
NEUTRON_L2_AGENT=vswitch
|
||||
NEUTRON_L3_EXT_BRIDGE=provider
|
||||
NEUTRON_ML2_MECHANISM_DRIVERS=vswitch,sriovnicswitch
|
||||
NEUTRON_ML2_TYPE_DRIVERS=managed_flat,managed_vlan,managed_vxlan
|
||||
NEUTRON_ML2_TENANT_NETWORK_TYPES=vlan,vxlan
|
||||
NEUTRON_ML2_SRIOV_AGENT_REQUIRED=False
|
||||
NEUTRON_HOST_DRIVER=neutron.plugins.wrs.drivers.host.DefaultHostDriver
|
||||
NEUTRON_FM_DRIVER=neutron.plugins.wrs.drivers.fm.DefaultFmDriver
|
||||
NEUTRON_NETWORK_SCHEDULER=neutron.scheduler.dhcp_host_agent_scheduler.HostChanceScheduler
|
||||
NEUTRON_ROUTER_SCHEDULER=neutron.scheduler.l3_host_agent_scheduler.HostChanceScheduler
|
||||
VSWITCH_TYPE=ovs-dpdk
|
||||
|
||||
[cSECURITY]
|
||||
[cREGION]
|
||||
|
@ -62,18 +62,7 @@ EXTERNAL_OAM_1_ADDRESS=abcd::4
|
||||
|
||||
[cNETWORK]
|
||||
# Data Network Configuration
|
||||
VSWITCH_TYPE=avs
|
||||
NEUTRON_L2_PLUGIN=ml2
|
||||
NEUTRON_L2_AGENT=vswitch
|
||||
NEUTRON_L3_EXT_BRIDGE=provider
|
||||
NEUTRON_ML2_MECHANISM_DRIVERS=vswitch,sriovnicswitch
|
||||
NEUTRON_ML2_TYPE_DRIVERS=managed_flat,managed_vlan,managed_vxlan
|
||||
NEUTRON_ML2_TENANT_NETWORK_TYPES=vlan,vxlan
|
||||
NEUTRON_ML2_SRIOV_AGENT_REQUIRED=False
|
||||
NEUTRON_HOST_DRIVER=neutron.plugins.wrs.drivers.host.DefaultHostDriver
|
||||
NEUTRON_FM_DRIVER=neutron.plugins.wrs.drivers.fm.DefaultFmDriver
|
||||
NEUTRON_NETWORK_SCHEDULER=neutron.scheduler.dhcp_host_agent_scheduler.HostChanceScheduler
|
||||
NEUTRON_ROUTER_SCHEDULER=neutron.scheduler.l3_host_agent_scheduler.HostChanceScheduler
|
||||
VSWITCH_TYPE=ovs-dpdk
|
||||
|
||||
[cSECURITY]
|
||||
[cREGION]
|
||||
|
@ -64,18 +64,7 @@ EXTERNAL_OAM_1_ADDRESS=10.10.10.4
|
||||
|
||||
[cNETWORK]
|
||||
# Data Network Configuration
|
||||
VSWITCH_TYPE=avs
|
||||
NEUTRON_L2_PLUGIN=ml2
|
||||
NEUTRON_L2_AGENT=vswitch
|
||||
NEUTRON_L3_EXT_BRIDGE=provider
|
||||
NEUTRON_ML2_MECHANISM_DRIVERS=vswitch,sriovnicswitch
|
||||
NEUTRON_ML2_TYPE_DRIVERS=managed_flat,managed_vlan,managed_vxlan
|
||||
NEUTRON_ML2_TENANT_NETWORK_TYPES=vlan,vxlan
|
||||
NEUTRON_ML2_SRIOV_AGENT_REQUIRED=False
|
||||
NEUTRON_HOST_DRIVER=neutron.plugins.wrs.drivers.host.DefaultHostDriver
|
||||
NEUTRON_FM_DRIVER=neutron.plugins.wrs.drivers.fm.DefaultFmDriver
|
||||
NEUTRON_NETWORK_SCHEDULER=neutron.scheduler.dhcp_host_agent_scheduler.HostChanceScheduler
|
||||
NEUTRON_ROUTER_SCHEDULER=neutron.scheduler.l3_host_agent_scheduler.HostChanceScheduler
|
||||
VSWITCH_TYPE=ovs-dpdk
|
||||
|
||||
[cSECURITY]
|
||||
[cREGION]
|
||||
|
@ -59,7 +59,7 @@ EXTERNAL_OAM_0_ADDRESS = 10.10.10.3
|
||||
EXTERNAL_OAM_1_ADDRESS = 10.10.10.4
|
||||
|
||||
[cNETWORK]
|
||||
VSWITCH_TYPE = avs
|
||||
VSWITCH_TYPE = ovs-dpdk
|
||||
|
||||
[cREGION]
|
||||
REGION_CONFIG = True
|
||||
|
@ -37,7 +37,7 @@ EXTERNAL_OAM_0_ADDRESS = 10.10.10.3
|
||||
EXTERNAL_OAM_1_ADDRESS = 10.10.10.4
|
||||
|
||||
[cNETWORK]
|
||||
VSWITCH_TYPE = avs
|
||||
VSWITCH_TYPE = ovs-dpdk
|
||||
|
||||
[cREGION]
|
||||
REGION_CONFIG = True
|
||||
|
@ -37,7 +37,7 @@ EXTERNAL_OAM_0_ADDRESS = 10.10.10.3
|
||||
EXTERNAL_OAM_1_ADDRESS = 10.10.10.4
|
||||
|
||||
[cNETWORK]
|
||||
VSWITCH_TYPE = avs
|
||||
VSWITCH_TYPE = ovs-dpdk
|
||||
|
||||
[cREGION]
|
||||
REGION_CONFIG = True
|
||||
|
@ -831,9 +831,9 @@ def test_region_config_validation():
|
||||
with pytest.raises(exceptions.ConfigFail):
|
||||
validate(region_config, REGION_CONFIG, None, False)
|
||||
|
||||
# Test detection of neutron in wrong region for AVS VSWITCH_TYPE
|
||||
# Test detection of neutron in wrong region for VSWITCH_TYPE
|
||||
region_config = cr.parse_system_config(nuage_vrs_regionfile)
|
||||
region_config.set('NETWORK', 'VSWITCH_TYPE', 'AVS')
|
||||
region_config.set('NETWORK', 'VSWITCH_TYPE', 'ovs-dpdk')
|
||||
with pytest.raises(exceptions.ConfigFail):
|
||||
cr.create_cgcs_config_file(None, region_config, None, None, None,
|
||||
validate_only=True)
|
||||
|
@ -1,6 +1,10 @@
|
||||
# compute specific configuration data
|
||||
---
|
||||
|
||||
# vswitch
|
||||
vswitch::dpdk::memory_channels: 4
|
||||
|
||||
|
||||
# neutron
|
||||
neutron::agents::dhcp::interface_driver: 'openvswitch'
|
||||
neutron::agents::dhcp::enable_isolated_metadata: true
|
||||
@ -11,6 +15,11 @@ neutron::agents::l3::interface_driver: 'openvswitch'
|
||||
neutron::agents::l3::metadata_port: 80
|
||||
neutron::agents::l3::agent_mode: 'dvr_snat'
|
||||
|
||||
neutron::agents::ml2::ovs::manage_vswitch: false
|
||||
neutron::agents::ml2::ovs::datapath_type: 'netdev'
|
||||
neutron::agents::ml2::ovs::vhostuser_socket_dir: '/var/run/openvswitch'
|
||||
neutron::agents::ml2::ovs::firewall_driver: 'noop'
|
||||
|
||||
neutron::agents::ml2::sriov::manage_service: true
|
||||
neutron::agents::ml2::sriov::polling_interval: 5
|
||||
|
||||
@ -46,6 +55,10 @@ nova::network::neutron::neutron_user_domain_name: 'Default'
|
||||
nova::network::neutron::neutron_project_domain_name: 'Default'
|
||||
nova::network::neutron::neutron_region_name: RegionOne
|
||||
|
||||
nova::compute::neutron::libvirt_vif_driver: 'nova.virt.libvirt.vif.LibvirtGenericVIFDriver'
|
||||
|
||||
openstack::nova::compute::compute_monitors: "cpu.virt_driver"
|
||||
|
||||
|
||||
# ceilometer
|
||||
ceilometer::agent::polling::central_namespace: false
|
||||
|
@ -133,6 +133,10 @@ sysinv::api::keystone_project_domain: 'Default'
|
||||
sysinv::conductor::enabled: false
|
||||
|
||||
|
||||
# nfvi
|
||||
nfv::nfvi::infrastructure_rest_api_data_port_fault_handling_enabled: false
|
||||
|
||||
|
||||
# keystone
|
||||
keystone::service::enabled: false
|
||||
keystone::token_provider: 'fernet'
|
||||
@ -235,12 +239,6 @@ nova_api_proxy::config::eventlet_pool_size: 256
|
||||
nova::db::sync_api::cellv2_setup: true
|
||||
|
||||
# neutron
|
||||
neutron::core_plugin: 'neutron.plugins.ml2.plugin.Ml2Plugin'
|
||||
neutron::service_plugins:
|
||||
- 'router'
|
||||
neutron::allow_overlapping_ips: true
|
||||
neutron::vlan_transparent: true
|
||||
neutron::pnet_audit_enabled: true
|
||||
|
||||
neutron::server::enabled: false
|
||||
neutron::server::database_idle_timeout: 60
|
||||
|
@ -35,12 +35,12 @@ neutron::logging::log_dir: false
|
||||
neutron::logging::verbose: false
|
||||
neutron::logging::debug: false
|
||||
|
||||
neutron::core_plugin: 'ml2'
|
||||
neutron::core_plugin: 'neutron.plugins.ml2.plugin.Ml2Plugin'
|
||||
neutron::service_plugins:
|
||||
- 'router'
|
||||
neutron::allow_overlapping_ips: true
|
||||
neutron::vlan_transparent: true
|
||||
neutron::pnet_audit_enabled: true
|
||||
neutron::pnet_audit_enabled: false
|
||||
|
||||
neutron::verbose: false
|
||||
neutron::root_helper: 'sudo'
|
||||
|
@ -4,9 +4,9 @@ class openstack::neutron::params (
|
||||
$region_name = undef,
|
||||
$service_name = 'openstack-neutron',
|
||||
$bgp_router_id = undef,
|
||||
$l3_agent_enabled = true,
|
||||
$service_create = false,
|
||||
$configure_endpoint = true
|
||||
$configure_endpoint = true,
|
||||
$tunnel_csum = undef,
|
||||
) { }
|
||||
|
||||
class openstack::neutron
|
||||
@ -20,7 +20,6 @@ class openstack::neutron
|
||||
class { '::neutron':
|
||||
rabbit_use_ssl => $::platform::amqp::params::ssl_enabled,
|
||||
default_transport_url => $::platform::amqp::params::transport_url,
|
||||
pnet_audit_enabled => $::platform::params::sdn_enabled ? { true => false, default => true },
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,8 +138,8 @@ class openstack::neutron::bgp
|
||||
|
||||
|
||||
class openstack::neutron::sfc (
|
||||
$sfc_drivers = undef,
|
||||
$flowclassifier_drivers = undef,
|
||||
$sfc_drivers = 'ovs',
|
||||
$flowclassifier_drivers = 'ovs',
|
||||
$sfc_quota_flow_classifier = undef,
|
||||
$sfc_quota_port_chain = undef,
|
||||
$sfc_quota_port_pair_group = undef,
|
||||
@ -197,9 +196,6 @@ class openstack::neutron::agents
|
||||
if str2bool($::disable_compute_services) {
|
||||
$pmon_ensure = absent
|
||||
|
||||
class {'::neutron::agents::vswitch':
|
||||
service_ensure => stopped,
|
||||
}
|
||||
class {'::neutron::agents::l3':
|
||||
enabled => false
|
||||
}
|
||||
@ -212,6 +208,9 @@ class openstack::neutron::agents
|
||||
class {'::neutron::agents::ml2::sriov':
|
||||
enabled => false
|
||||
}
|
||||
class {'::neutron::agents::ml2::ovs':
|
||||
enabled => false
|
||||
}
|
||||
} else {
|
||||
$pmon_ensure = link
|
||||
|
||||
@ -219,12 +218,21 @@ class openstack::neutron::agents
|
||||
metadata_workers => $::platform::params::eng_workers_by_4
|
||||
}
|
||||
|
||||
class { '::neutron::agents::l3':
|
||||
enabled => $l3_agent_enabled,
|
||||
}
|
||||
|
||||
include ::neutron::agents::dhcp
|
||||
include ::neutron::agents::l3
|
||||
include ::neutron::agents::ml2::sriov
|
||||
include ::neutron::agents::ml2::ovs
|
||||
}
|
||||
|
||||
if $::platform::params::vswitch_type =~ '^ovs' {
|
||||
# Ensure bridges and addresses are configured before agent is started
|
||||
Platform::Vswitch::Ovs::Bridge<||> ~> Service['neutron-ovs-agent-service']
|
||||
Platform::Vswitch::Ovs::Address<||> ~> Service['neutron-ovs-agent-service']
|
||||
|
||||
# Enable/disable tunnel checksum
|
||||
neutron_agent_ovs {
|
||||
'agent/tunnel_csum': value => $tunnel_csum;
|
||||
}
|
||||
}
|
||||
|
||||
file { "/etc/pmon.d/neutron-dhcp-agent.conf":
|
||||
|
@ -136,6 +136,7 @@ class openstack::nova::compute (
|
||||
$migration_key_type,
|
||||
$pci_pt_whitelist = [],
|
||||
$pci_sriov_whitelist = undef,
|
||||
$compute_monitors,
|
||||
$iscsi_initiator_name = undef,
|
||||
) inherits ::openstack::nova::params {
|
||||
include ::nova::pci
|
||||
@ -145,6 +146,7 @@ class openstack::nova::compute (
|
||||
include ::platform::network::infra::params
|
||||
include ::nova::keystone::auth
|
||||
include ::nova::keystone::authtoken
|
||||
include ::nova::compute::neutron
|
||||
|
||||
include ::openstack::nova::sshd
|
||||
|
||||
@ -268,8 +270,6 @@ class openstack::nova::compute (
|
||||
$libvirt_images_type = "default"
|
||||
}
|
||||
|
||||
$compute_monitors = "cpu.virt_driver"
|
||||
|
||||
class { '::nova::compute::libvirt':
|
||||
libvirt_virt_type => $libvirt_virt_type,
|
||||
vncserver_listen => $libvirt_vnc_bind_host,
|
||||
@ -336,11 +336,6 @@ class openstack::nova::compute (
|
||||
match => '^cgroup_controllers = .*',
|
||||
}
|
||||
|
||||
class { '::nova::compute::neutron':
|
||||
libvirt_vif_driver => 'nova.virt.libvirt.vif.LibvirtGenericVIFDriver',
|
||||
libvirt_qemu_dpdk_options => 'type=secondary,prefix=vs,channels=4,cpu=0',
|
||||
}
|
||||
|
||||
# The pci_passthrough option in the nova::compute class is not sufficient.
|
||||
# In particular, it sets the pci_passthrough_whitelist in nova.conf to an
|
||||
# empty string if the list is empty, causing the nova-compute process to fail.
|
||||
|
@ -72,10 +72,12 @@ class platform::config::file {
|
||||
}
|
||||
}
|
||||
|
||||
file_line { "${platform_conf} vswitch_type":
|
||||
path => $platform_conf,
|
||||
line => "vswitch_type=${::platform::params::vswitch_type}",
|
||||
match => '^vswitch_type=',
|
||||
if $::platform::params::vswitch_type {
|
||||
file_line { "${platform_conf} vswitch_type":
|
||||
path => $platform_conf,
|
||||
line => "vswitch_type=${::platform::params::vswitch_type}",
|
||||
match => '^vswitch_type=',
|
||||
}
|
||||
}
|
||||
|
||||
if $::platform::params::system_type {
|
||||
|
@ -29,8 +29,8 @@ class platform::ntp (
|
||||
onlyif => "grep -q '^server' /etc/ntp.conf",
|
||||
}
|
||||
|
||||
exec { 'systemd-daemon-reload':
|
||||
command => '/usr/bin/systemctl daemon-reload',
|
||||
exec { 'ntpdate-systemd-daemon-reload':
|
||||
command => '/usr/bin/systemctl daemon-reload',
|
||||
}
|
||||
|
||||
exec { 'stop-ntpdate':
|
||||
@ -57,7 +57,7 @@ class platform::ntp (
|
||||
File['ntpdate_tis_override'] ->
|
||||
Exec['enable-ntpdate'] ->
|
||||
Exec['enable-ntpd'] ->
|
||||
Exec['systemd-daemon-reload'] ->
|
||||
Exec['ntpdate-systemd-daemon-reload'] ->
|
||||
Exec['stop-ntpdate'] ->
|
||||
Exec['stop-ntpd'] ->
|
||||
Exec['start-ntpdate'] ->
|
||||
|
@ -1,35 +1,130 @@
|
||||
class platform::vswitch {
|
||||
class platform::vswitch::params(
|
||||
$iommu_enabled = true,
|
||||
$hugepage_dir = '/mnt/huge-1048576kB',
|
||||
$driver_type = 'vfio-pci',
|
||||
) { }
|
||||
|
||||
|
||||
class platform::vswitch
|
||||
inherits ::platform::vswitch::params {
|
||||
|
||||
Class[$name] -> Class['::platform::network']
|
||||
Mount[$hugepage_dir] -> Class[$name]
|
||||
|
||||
include ::platform::vswitch::ovsdb
|
||||
$enable_unsafe_noiommu_mode = bool2num(!$iommu_enabled)
|
||||
|
||||
exec {'vfio-iommu-mode':
|
||||
command => "echo ${enable_unsafe_noiommu_mode} > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
|
||||
require => Kmod::Load[$driver_type],
|
||||
}
|
||||
|
||||
include ::platform::vswitch::ovs
|
||||
}
|
||||
|
||||
|
||||
class platform::vswitch::ovsdb {
|
||||
include ::platform::params
|
||||
|
||||
if $::platform::params::sdn_enabled {
|
||||
$pmon_ensure = 'link'
|
||||
$service_ensure = 'running'
|
||||
} else {
|
||||
$pmon_ensure = 'absent'
|
||||
$service_ensure = 'stopped'
|
||||
define platform::vswitch::ovs::device(
|
||||
$pci_addr,
|
||||
$driver_type,
|
||||
) {
|
||||
exec { "ovs-bind-device: $title":
|
||||
path => ["/usr/bin", "/usr/sbin", "/usr/share/openvswitch/scripts"],
|
||||
command => "dpdk-devbind.py --bind=${driver_type} ${pci_addr}"
|
||||
}
|
||||
|
||||
# ensure pmon soft link
|
||||
file { "/etc/pmon.d/ovsdb-server.conf":
|
||||
ensure => $pmon_ensure,
|
||||
target => "/etc/openvswitch/ovsdb-server.pmon.conf",
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
}
|
||||
|
||||
# service management (start ovsdb-server)
|
||||
service { "openvswitch":
|
||||
ensure => $service_ensure,
|
||||
enable => $::platform::params::sdn_enabled,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
define platform::vswitch::ovs::bridge(
|
||||
$datapath_type = 'netdev',
|
||||
) {
|
||||
exec { "ovs-add-br: ${title}":
|
||||
command => template("platform/ovs.add-bridge.erb")
|
||||
} ->
|
||||
exec { "ovs-link-up: ${title}":
|
||||
command => "ip link set ${name} up",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
define platform::vswitch::ovs::port(
|
||||
$type = 'port',
|
||||
$bridge,
|
||||
$attributes = [],
|
||||
$interfaces,
|
||||
) {
|
||||
exec { "ovs-add-port: ${title}":
|
||||
command => template("platform/ovs.add-port.erb"),
|
||||
logoutput => true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
define platform::vswitch::ovs::address(
|
||||
$ifname,
|
||||
$address,
|
||||
$prefixlen,
|
||||
) {
|
||||
exec { "ovs-add-address: ${title}":
|
||||
command => "ip addr replace ${address}/${prefixlen} dev ${ifname}",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class platform::vswitch::ovs(
|
||||
$devices = {},
|
||||
$bridges = {},
|
||||
$ports = {},
|
||||
$addresses = {},
|
||||
) inherits ::platform::vswitch::params {
|
||||
|
||||
if $::platform::params::vswitch_type == 'ovs' {
|
||||
include ::vswitch::ovs
|
||||
} elsif $::platform::params::vswitch_type == 'ovs-dpdk' {
|
||||
include ::vswitch::dpdk
|
||||
|
||||
Exec['vfio-iommu-mode'] ->
|
||||
Platform::Vswitch::Ovs::Device<||> ->
|
||||
Platform::Vswitch::Ovs::Bridge<||>
|
||||
|
||||
create_resources('platform::vswitch::ovs::device', $devices, {
|
||||
driver_type => $driver_type,
|
||||
before => Service['openvswitch']
|
||||
})
|
||||
|
||||
$dpdk_configs = {
|
||||
'other_config:dpdk-hugepage-dir' => { value => $hugepage_dir },
|
||||
}
|
||||
|
||||
$dpdk_dependencies = {
|
||||
wait => false,
|
||||
require => Service['openvswitch'],
|
||||
notify => Vs_config['other_config:dpdk-init'],
|
||||
}
|
||||
|
||||
create_resources ('vs_config', $dpdk_configs, $dpdk_dependencies)
|
||||
}
|
||||
|
||||
if $::platform::params::vswitch_type =~ '^ovs' {
|
||||
|
||||
# clean bridges and ports before applying current configuration
|
||||
exec { "ovs-clean":
|
||||
command => template("platform/ovs.clean.erb"),
|
||||
provider => shell,
|
||||
require => Service['openvswitch']
|
||||
} ->
|
||||
|
||||
Platform::Vswitch::Ovs::Bridge<||> -> Platform::Vswitch::Ovs::Port<||>
|
||||
Platform::Vswitch::Ovs::Bridge<||> -> Platform::Vswitch::Ovs::Address<||>
|
||||
}
|
||||
|
||||
create_resources('platform::vswitch::ovs::bridge', $bridges, {
|
||||
require => Service['openvswitch']
|
||||
})
|
||||
|
||||
create_resources('platform::vswitch::ovs::port', $ports, {
|
||||
require => Service['openvswitch']
|
||||
})
|
||||
|
||||
create_resources('platform::vswitch::ovs::address', $addresses, {
|
||||
require => Service['openvswitch']
|
||||
})
|
||||
}
|
||||
|
@ -0,0 +1,2 @@
|
||||
ovs-vsctl --timeout 10 -- --may-exist add-br <%= @name -%>
|
||||
-- set bridge <%= @name -%> datapath_type=<%= @datapath_type -%>
|
@ -0,0 +1,16 @@
|
||||
ovs-vsctl --timeout 10 -- --may-exist add-<%= @type -%> <%= @bridge -%> <%= @name -%>
|
||||
<%- if @type == 'bond' -%>
|
||||
<%- @interfaces.each do |interface| -%>
|
||||
<%= interface['name'] -%>
|
||||
<%- end -%>
|
||||
<%- end -%>
|
||||
<%- @attributes.each do |attribute| -%>
|
||||
<%= attribute -%>
|
||||
<%- end -%>
|
||||
<%- @interfaces.each do |interface| -%>
|
||||
-- set Interface <%= interface['name'] -%>
|
||||
type=<%= interface['type'] -%>
|
||||
<%- interface['attributes'].each do |attribute| -%>
|
||||
<%= attribute -%>
|
||||
<%- end -%>
|
||||
<%- end -%>
|
@ -0,0 +1,7 @@
|
||||
# clean provider network ports and bridges
|
||||
for bridge in $(ovs-vsctl --timeout 10 list-br|grep '^br-phy'); do
|
||||
for port in $(ovs-vsctl --timeout 10 list-ports $bridge); do
|
||||
ovs-vsctl --timeout 10 del-port $bridge $port
|
||||
done
|
||||
ovs-vsctl --timeout 10 del-br $bridge
|
||||
done
|
@ -0,0 +1,7 @@
|
||||
# delete manager
|
||||
ovs-vsctl -t ovsdb-server --no-wait del-manager
|
||||
|
||||
# delete all bridges
|
||||
for bridge in $(ovs-vsctl -t ovsdb-server --timeout 10 list-br); do
|
||||
ovs-vsctl -t ovsdb-server --timeout 10 --no-wait del-br $bridge
|
||||
done
|
@ -12,8 +12,8 @@ from cgtsclient import exc
|
||||
|
||||
CREATION_ATTRIBUTES = ['ihost_uuid', 'memtotal_mib', 'memavail_mib',
|
||||
'platform_reserved_mib', 'hugepages_configured',
|
||||
'avs_hugepages_size_mib', 'avs_hugepages_reqd',
|
||||
'avs_hugepages_nr', 'avs_hugepages_avail',
|
||||
'vswitch_hugepages_size_mib', 'vswitch_hugepages_reqd',
|
||||
'vswitch_hugepages_nr', 'vswitch_hugepages_avail',
|
||||
'vm_hugepages_nr_2M_pending', 'vm_hugepages_nr_1G_pending',
|
||||
'vm_hugepages_nr_2M', 'vm_hugepages_avail_2M',
|
||||
'vm_hugepages_nr_1G', 'vm_hugepages_avail_1G',
|
||||
@ -21,6 +21,7 @@ CREATION_ATTRIBUTES = ['ihost_uuid', 'memtotal_mib', 'memavail_mib',
|
||||
'vm_hugepages_possible_2M', 'vm_hugepages_possible_1G',
|
||||
'capabilities', 'numa_node', 'minimum_platform_reserved_mib']
|
||||
|
||||
|
||||
class imemory(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<imemory %s>" % self._info
|
||||
|
@ -12,17 +12,17 @@
|
||||
|
||||
from cgtsclient.common import utils
|
||||
from cgtsclient import exc
|
||||
from collections import OrderedDict
|
||||
from cgtsclient.v1 import ihost as ihost_utils
|
||||
|
||||
|
||||
def _print_imemory_show(imemory):
|
||||
fields = ['memtotal_mib',
|
||||
'platform_reserved_mib',
|
||||
'memavail_mib',
|
||||
'hugepages_configured',
|
||||
'avs_hugepages_size_mib',
|
||||
'avs_hugepages_nr',
|
||||
'avs_hugepages_avail',
|
||||
'vswitch_hugepages_size_mib',
|
||||
'vswitch_hugepages_nr',
|
||||
'vswitch_hugepages_avail',
|
||||
'vm_hugepages_nr_4K',
|
||||
'vm_hugepages_nr_2M',
|
||||
'vm_hugepages_nr_2M_pending',
|
||||
@ -36,9 +36,9 @@ def _print_imemory_show(imemory):
|
||||
' Platform (MiB)',
|
||||
' Available (MiB)',
|
||||
'Huge Pages Configured',
|
||||
'AVS Huge Pages: Size (MiB)',
|
||||
' Total',
|
||||
' Available',
|
||||
'vSwitch Huge Pages: Size (MiB)',
|
||||
' Total',
|
||||
' Available',
|
||||
'VM Pages (4K): Total',
|
||||
'VM Huge Pages (2M): Total',
|
||||
' Total Pending',
|
||||
@ -110,9 +110,9 @@ def do_host_memory_list(cc, args):
|
||||
'platform_reserved_mib',
|
||||
'memavail_mib',
|
||||
'hugepages_configured',
|
||||
'avs_hugepages_size_mib',
|
||||
'avs_hugepages_nr',
|
||||
'avs_hugepages_avail',
|
||||
'vswitch_hugepages_size_mib',
|
||||
'vswitch_hugepages_nr',
|
||||
'vswitch_hugepages_avail',
|
||||
'vm_hugepages_nr_4K',
|
||||
'vm_hugepages_nr_2M',
|
||||
'vm_hugepages_avail_2M',
|
||||
@ -123,21 +123,21 @@ def do_host_memory_list(cc, args):
|
||||
'vm_hugepages_use_1G']
|
||||
|
||||
field_labels = ['processor',
|
||||
'mem_total(MiB)',
|
||||
'mem_platform(MiB)',
|
||||
'mem_avail(MiB)',
|
||||
'hugepages(hp)_configured',
|
||||
'avs_hp_size(MiB)',
|
||||
'avs_hp_total',
|
||||
'avs_hp_avail',
|
||||
'vm_total_4K',
|
||||
'vm_hp_total_2M',
|
||||
'vm_hp_avail_2M',
|
||||
'vm_hp_pending_2M',
|
||||
'vm_hp_total_1G',
|
||||
'vm_hp_avail_1G',
|
||||
'vm_hp_pending_1G',
|
||||
'vm_hp_use_1G']
|
||||
'mem_total(MiB)',
|
||||
'mem_platform(MiB)',
|
||||
'mem_avail(MiB)',
|
||||
'hugepages(hp)_configured',
|
||||
'vs_hp_size(MiB)',
|
||||
'vs_hp_total',
|
||||
'vs_hp_avail',
|
||||
'vm_total_4K',
|
||||
'vm_hp_total_2M',
|
||||
'vm_hp_avail_2M',
|
||||
'vm_hp_pending_2M',
|
||||
'vm_hp_total_1G',
|
||||
'vm_hp_avail_1G',
|
||||
'vm_hp_pending_1G',
|
||||
'vm_hp_use_1G']
|
||||
|
||||
utils.print_list(imemorys, fields, field_labels, sortby=1)
|
||||
|
||||
|
@ -42,6 +42,11 @@ def _print_isystem_show(isystem):
|
||||
setattr(isystem, 'distributed_cloud_role',
|
||||
isystem.distributed_cloud_role)
|
||||
|
||||
if isystem.capabilities.get('vswitch_type') is not None:
|
||||
fields.append('vswitch_type')
|
||||
setattr(isystem, 'vswitch_type',
|
||||
isystem.capabilities.get('vswitch_type'))
|
||||
|
||||
data = dict(list([(f, getattr(isystem, f, '')) for f in fields]))
|
||||
utils.print_dict(data)
|
||||
|
||||
@ -78,7 +83,10 @@ def do_show(cc, args):
|
||||
metavar='<https_enabled>',
|
||||
choices=['true', 'false'],
|
||||
help='The HTTPS enabled or disabled flag')
|
||||
|
||||
@utils.arg('-v', '--vswitch_type',
|
||||
metavar='<vswitch_type>',
|
||||
choices=['ovs-dpdk'],
|
||||
help='The vswitch type for the system')
|
||||
def do_modify(cc, args):
|
||||
"""Modify system attributes."""
|
||||
|
||||
@ -126,7 +134,7 @@ def do_modify(cc, args):
|
||||
print 'Please follow the admin guide to complete the reconfiguration.'
|
||||
|
||||
field_list = ['name', 'system_mode', 'description', 'location', 'contact',
|
||||
'timezone', 'sdn_enabled','https_enabled']
|
||||
'timezone', 'sdn_enabled','https_enabled', 'vswitch_type']
|
||||
|
||||
# use field list as filter
|
||||
user_fields = dict((k, v) for (k, v) in vars(args).items()
|
||||
|
@ -74,9 +74,8 @@ install -m 644 -p -D scripts/sysinv-conductor.service %{buildroot}%{_unitdir}/sy
|
||||
|
||||
install -d -m 755 %{buildroot}%{local_bindir}
|
||||
install -p -D -m 755 sysinv/cmd/partition_info.sh %{buildroot}%{local_bindir}/partition_info.sh
|
||||
|
||||
install -d -m 755 %{buildroot}%{local_bindir}
|
||||
install -p -D -m 755 sysinv/cmd/manage-partitions %{buildroot}%{local_bindir}/manage-partitions
|
||||
install -p -D -m 755 sysinv/cmd/query_pci_id %{buildroot}%{local_bindir}/query_pci_id
|
||||
|
||||
%clean
|
||||
echo "CLEAN CALLED"
|
||||
|
@ -29,11 +29,10 @@ import tsconfig.tsconfig as tsc
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# Defines per-socket AVS memory requirements (in MB) for both real and virtual
|
||||
# deployments
|
||||
#
|
||||
AVS_REAL_MEMORY_MB = 1024
|
||||
AVS_VBOX_MEMORY_MB = 512
|
||||
# Defines per-socket vswitch memory requirements (in MB) for both real and
|
||||
# virtual deployments
|
||||
VSWITCH_REAL_MEMORY_MB = 1024
|
||||
VSWITCH_VIRTUAL_MEMORY_MB = 512
|
||||
|
||||
|
||||
class CPU:
|
||||
@ -286,32 +285,32 @@ class NodeOperator(object):
|
||||
return [name for name in listdir(dir)
|
||||
if os.path.isdir(join(dir, name))]
|
||||
|
||||
def _set_default_avs_hugesize(self):
|
||||
'''
|
||||
Set the default memory size for avs hugepages when it must fallback to
|
||||
2MB pages because there are no 1GB pages. In a virtual environment we
|
||||
set a smaller amount of memory because AVS is configured to use a
|
||||
smaller mbuf pool. In non-virtual environments we use the same amount
|
||||
of memory as we would if 1GB pages were available.
|
||||
'''
|
||||
def _set_default_vswitch_hugesize(self):
|
||||
"""
|
||||
Set the default memory size for vswitch hugepages when it must fallback
|
||||
to 2MB pages because there are no 1GB pages. In a virtual environment
|
||||
we set a smaller amount of memory because vswitch is configured to use
|
||||
a smaller mbuf pool. In non-virtual environments we use the same
|
||||
amount of memory as we would if 1GB pages were available.
|
||||
"""
|
||||
hugepage_size = 2
|
||||
if utils.is_virtual():
|
||||
avs_hugepages_nr = AVS_VBOX_MEMORY_MB / hugepage_size
|
||||
vswitch_hugepages_nr = VSWITCH_VIRTUAL_MEMORY_MB / hugepage_size
|
||||
else:
|
||||
avs_hugepages_nr = AVS_REAL_MEMORY_MB / hugepage_size
|
||||
vswitch_hugepages_nr = VSWITCH_REAL_MEMORY_MB / hugepage_size
|
||||
|
||||
## Create a new set of dict attributes
|
||||
hp_attr = {'avs_hugepages_size_mib': hugepage_size,
|
||||
'avs_hugepages_nr': avs_hugepages_nr,
|
||||
'avs_hugepages_avail': 0}
|
||||
hp_attr = {'vswitch_hugepages_size_mib': hugepage_size,
|
||||
'vswitch_hugepages_nr': vswitch_hugepages_nr,
|
||||
'vswitch_hugepages_avail': 0}
|
||||
return hp_attr
|
||||
|
||||
def _inode_get_memory_hugepages(self):
|
||||
'''Collect hugepage info, including avs, and vm.
|
||||
"""Collect hugepage info, including vswitch, and vm.
|
||||
Collect platform reserved if config.
|
||||
:param self
|
||||
:returns list of memory nodes and attributes
|
||||
'''
|
||||
"""
|
||||
|
||||
imemory = []
|
||||
Ki = 1024
|
||||
@ -339,7 +338,7 @@ class NodeOperator(object):
|
||||
Total_HP_MiB = 0 # Total memory (MiB) currently configured in HPs
|
||||
Free_HP_MiB = 0
|
||||
|
||||
# Check AVS and Libvirt memory
|
||||
# Check vswitch and libvirt memory
|
||||
# Loop through configured hugepage sizes of this node and record
|
||||
# total number and number free
|
||||
hugepages = "/sys/devices/system/node/node%d/hugepages" % node
|
||||
@ -352,7 +351,7 @@ class NodeOperator(object):
|
||||
sizesplit = subdir.split('-')
|
||||
# role via size; also from /etc/nova/compute_reserved.conf
|
||||
if sizesplit[1].startswith("1048576kB"):
|
||||
hugepages_role = "avs"
|
||||
hugepages_role = "vswitch"
|
||||
size = int(SZ_1G_Ki / Ki)
|
||||
else:
|
||||
hugepages_role = "vm"
|
||||
@ -377,27 +376,27 @@ class NodeOperator(object):
|
||||
|
||||
# Libvirt hugepages can now be 1G and 2M, can't only look
|
||||
# at 2M pages
|
||||
if hugepages_role == "avs":
|
||||
avs_hugepages_nr = AVS_REAL_MEMORY_MB / size
|
||||
if hugepages_role == "vswitch":
|
||||
vswitch_hugepages_nr = VSWITCH_REAL_MEMORY_MB / size
|
||||
hp_attr = {
|
||||
'avs_hugepages_size_mib': size,
|
||||
'avs_hugepages_nr': avs_hugepages_nr,
|
||||
'avs_hugepages_avail': 0,
|
||||
'vswitch_hugepages_size_mib': size,
|
||||
'vswitch_hugepages_nr': vswitch_hugepages_nr,
|
||||
'vswitch_hugepages_avail': 0,
|
||||
'vm_hugepages_nr_1G':
|
||||
(nr_hugepages - avs_hugepages_nr),
|
||||
(nr_hugepages - vswitch_hugepages_nr),
|
||||
'vm_hugepages_avail_1G': free_hugepages,
|
||||
'vm_hugepages_use_1G': 'True'
|
||||
}
|
||||
else:
|
||||
if len(subdirs) == 1:
|
||||
hp_attr = self._set_default_avs_hugesize()
|
||||
hp_attr = self._set_default_vswitch_hugesize()
|
||||
hp_attr.update({'vm_hugepages_use_1G': 'False'})
|
||||
|
||||
avs_hugepages_nr = hp_attr.get('avs_hugepages_nr', 0)
|
||||
vswitch_hugepages_nr = hp_attr.get('vswitch_hugepages_nr', 0)
|
||||
hp_attr.update({
|
||||
'vm_hugepages_avail_2M': free_hugepages,
|
||||
'vm_hugepages_nr_2M':
|
||||
(nr_hugepages - avs_hugepages_nr)
|
||||
(nr_hugepages - vswitch_hugepages_nr)
|
||||
})
|
||||
|
||||
attr.update(hp_attr)
|
||||
@ -503,8 +502,8 @@ class NodeOperator(object):
|
||||
|
||||
Eng_KiB = node_total_kib - base_mem_MiB * Ki
|
||||
|
||||
vswitch_mem_kib = (attr.get('avs_hugepages_size_mib', 0) *
|
||||
attr.get('avs_hugepages_nr', 0) * Ki)
|
||||
vswitch_mem_kib = (attr.get('vswitch_hugepages_size_mib', 0) *
|
||||
attr.get('vswitch_hugepages_nr', 0) * Ki)
|
||||
|
||||
VM_KiB = (Eng_KiB - vswitch_mem_kib)
|
||||
|
||||
|
@ -463,19 +463,13 @@ class PCIOperator(object):
|
||||
|
||||
try:
|
||||
with open(os.devnull, "w") as fnull:
|
||||
"""
|
||||
query_pci_id is from dpdk (avs/cgcs-dpdk/files/query_pci_id).
|
||||
DPDK is removed as part of AVS.
|
||||
Need add it back later. Then enable this code again.
|
||||
"""
|
||||
LOG.error("******ERROR: unable to determine DPDK support or not due to lack DPDK package.******")
|
||||
# subprocess.check_call(["query_pci_id", "-v " + str(vendor),
|
||||
# "-d " + str(device)],
|
||||
# stdout=fnull, stderr=fnull)
|
||||
# dpdksupport = True
|
||||
# LOG.debug("DPDK does support NIC "
|
||||
# "(vendor: %s device: %s)",
|
||||
# vendor, device)
|
||||
subprocess.check_call(["query_pci_id", "-v " + str(vendor),
|
||||
"-d " + str(device)],
|
||||
stdout=fnull, stderr=fnull)
|
||||
dpdksupport = True
|
||||
LOG.debug("DPDK does support NIC "
|
||||
"(vendor: %s device: %s)",
|
||||
vendor, device)
|
||||
except subprocess.CalledProcessError as e:
|
||||
dpdksupport = False
|
||||
if e.returncode == '1':
|
||||
|
@ -141,7 +141,7 @@ class EthernetPort(base.APIBase):
|
||||
"Represent whether the port is a boot port"
|
||||
|
||||
dpdksupport = bool
|
||||
"Represent whether or not the port supported AVS acceleration"
|
||||
"Represent whether or not the port supports DPDK acceleration"
|
||||
|
||||
host_uuid = types.uuid
|
||||
"Represent the UUID of the host the port belongs to"
|
||||
|
@ -3143,10 +3143,6 @@ class HostController(rest.RestController):
|
||||
Perform semantic checks against data interfaces to ensure validity of
|
||||
the node configuration prior to unlocking it.
|
||||
"""
|
||||
vswitch_type = utils.get_vswitch_type()
|
||||
if vswitch_type != constants.VSWITCH_TYPE_AVS:
|
||||
return
|
||||
|
||||
ihost_iinterfaces = (
|
||||
pecan.request.dbapi.iinterface_get_by_ihost(ihost['uuid']))
|
||||
data_interface_configured = False
|
||||
@ -3172,10 +3168,6 @@ class HostController(rest.RestController):
|
||||
controller will be confused on won't know how to map the VXLAN VTEP
|
||||
endpoints.
|
||||
"""
|
||||
vswitch_type = utils.get_vswitch_type()
|
||||
if vswitch_type != constants.VSWITCH_TYPE_AVS:
|
||||
return
|
||||
|
||||
sdn_enabled = utils.get_sdn_enabled()
|
||||
if not sdn_enabled:
|
||||
return
|
||||
@ -3431,7 +3423,7 @@ class HostController(rest.RestController):
|
||||
memtotal = m.node_memtotal_mib
|
||||
allocated = m.platform_reserved_mib
|
||||
if m.hugepages_configured:
|
||||
allocated += m.avs_hugepages_nr * m.avs_hugepages_size_mib
|
||||
allocated += m.vswitch_hugepages_nr * m.vswitch_hugepages_size_mib
|
||||
if m.vm_hugepages_nr_2M_pending is not None:
|
||||
allocated += constants.MIB_2M * m.vm_hugepages_nr_2M_pending
|
||||
pending_2M_memory = True
|
||||
@ -3499,7 +3491,7 @@ class HostController(rest.RestController):
|
||||
vm_hugepages_4K = \
|
||||
(m.node_memtotal_mib - m.platform_reserved_mib)
|
||||
vm_hugepages_4K -= \
|
||||
(m.avs_hugepages_nr * m.avs_hugepages_size_mib)
|
||||
(m.vswitch_hugepages_nr * m.vswitch_hugepages_size_mib)
|
||||
vm_hugepages_4K -= \
|
||||
(constants.MIB_2M * vm_hugepages_nr_2M)
|
||||
vm_hugepages_4K -= \
|
||||
|
@ -878,8 +878,6 @@ def _valid_network_types():
|
||||
vswitch_type = utils.get_vswitch_type()
|
||||
system_mode = utils.get_system_mode()
|
||||
|
||||
if vswitch_type != constants.VSWITCH_TYPE_AVS:
|
||||
valid_types -= set([constants.NETWORK_TYPE_DATA])
|
||||
if vswitch_type != constants.VSWITCH_TYPE_NUAGE_VRS:
|
||||
valid_types -= set([constants.NETWORK_TYPE_DATA_VRS])
|
||||
if system_mode == constants.SYSTEM_MODE_SIMPLEX:
|
||||
@ -1200,7 +1198,7 @@ def _check_interface_data(op, interface, ihost, existing_interface):
|
||||
# check mode/pool combinations and transitions for validity
|
||||
_check_address_mode(op, interface, ihost, existing_interface)
|
||||
|
||||
# Make sure txhashpolicy for data is layer2 ... all that AVS supports
|
||||
# Make sure txhashpolicy for data is layer2
|
||||
aemode = interface['aemode']
|
||||
txhashpolicy = interface['txhashpolicy']
|
||||
|
||||
@ -1821,15 +1819,16 @@ def _neutron_host_extension_supported():
|
||||
necessary or not. If it is not supported then this is an indication that
|
||||
we are running against a vanilla openstack installation.
|
||||
"""
|
||||
return bool(utils.get_vswitch_type() == constants.VSWITCH_TYPE_AVS)
|
||||
## TODO: Rather than key off of the vswitch type this should be looking at
|
||||
## the neutron extension list, but because our config file is not setup
|
||||
## properly to have a different region on a per service basis we cannot.
|
||||
## The code should like something like this:
|
||||
##
|
||||
## extensions = pecan.request.rpcapi.neutron_extension_list(
|
||||
## pecan.request.context)
|
||||
## return bool(constants.NEUTRON_HOST_ALIAS in extensions)
|
||||
return True
|
||||
# TODO: This should be looking at the neutron extension list, but because
|
||||
# our config file is not setup properly to have a different region on a per
|
||||
# service basis we cannot.
|
||||
#
|
||||
# The code should like something like this:
|
||||
#
|
||||
# extensions = pecan.request.rpcapi.neutron_extension_list(
|
||||
# pecan.request.context)
|
||||
# return bool(constants.NEUTRON_HOST_ALIAS in extensions)
|
||||
|
||||
|
||||
def _neutron_providernet_extension_supported():
|
||||
@ -1839,15 +1838,16 @@ def _neutron_providernet_extension_supported():
|
||||
necessary or not. If it is not supported then this is an indication that
|
||||
we are running against a vanilla openstack installation.
|
||||
"""
|
||||
return bool(utils.get_vswitch_type() == constants.VSWITCH_TYPE_AVS)
|
||||
## TODO: Rather than key off of the vswitch type this should be looking at
|
||||
## the neutron extension list, but because our config file is not setup
|
||||
## properly to have a different region on a per service basis we cannot.
|
||||
## The code should like something like this:
|
||||
##
|
||||
## extensions = pecan.request.rpcapi.neutron_extension_list(
|
||||
## pecan.request.context)
|
||||
## return bool(constants.NEUTRON_WRS_PROVIDER_ALIAS in extensions)
|
||||
return True
|
||||
# TODO: This should be looking at the neutron extension list, but because
|
||||
# our config file is not setup properly to have a different region on a per
|
||||
# service basis we cannot.
|
||||
#
|
||||
# The code should like something like this:
|
||||
#
|
||||
# extensions = pecan.request.rpcapi.neutron_extension_list(
|
||||
# pecan.request.context)
|
||||
# return bool(constants.NEUTRON_WRS_PROVIDER_ALIAS in extensions)
|
||||
|
||||
|
||||
def _neutron_providernet_list():
|
||||
|
@ -94,17 +94,17 @@ class Memory(base.APIBase):
|
||||
hugepages_configured = wtypes.text
|
||||
"Represent whether huge pages are configured"
|
||||
|
||||
avs_hugepages_size_mib = int
|
||||
"Represent the imemory avs huge pages size in MiB"
|
||||
vswitch_hugepages_size_mib = int
|
||||
"Represent the imemory vswitch huge pages size in MiB"
|
||||
|
||||
avs_hugepages_reqd = int
|
||||
"Represent the imemory avs required number of hugepages"
|
||||
vswitch_hugepages_reqd = int
|
||||
"Represent the imemory vswitch required number of hugepages"
|
||||
|
||||
avs_hugepages_nr = int
|
||||
"Represent the imemory avs number of hugepages"
|
||||
vswitch_hugepages_nr = int
|
||||
"Represent the imemory vswitch number of hugepages"
|
||||
|
||||
avs_hugepages_avail = int
|
||||
"Represent the imemory avs number of hugepages available"
|
||||
vswitch_hugepages_avail = int
|
||||
"Represent the imemory vswitch number of hugepages available"
|
||||
|
||||
vm_hugepages_nr_2M_pending = int
|
||||
"Represent the imemory vm number of hugepages pending (2M pages)"
|
||||
@ -182,9 +182,9 @@ class Memory(base.APIBase):
|
||||
if not expand:
|
||||
memory.unset_fields_except(['uuid', 'memtotal_mib', 'memavail_mib',
|
||||
'platform_reserved_mib', 'hugepages_configured',
|
||||
'avs_hugepages_size_mib', 'avs_hugepages_nr',
|
||||
'avs_hugepages_reqd',
|
||||
'avs_hugepages_avail',
|
||||
'vswitch_hugepages_size_mib', 'vswitch_hugepages_nr',
|
||||
'vswitch_hugepages_reqd',
|
||||
'vswitch_hugepages_avail',
|
||||
'vm_hugepages_nr_2M',
|
||||
'vm_hugepages_nr_1G', 'vm_hugepages_use_1G',
|
||||
'vm_hugepages_nr_2M_pending',
|
||||
@ -576,10 +576,10 @@ def _check_memory(rpc_port, ihost, platform_reserved_mib=None,
|
||||
mem_alloc += int(rpc_port['vm_hugepages_nr_1G']) * 1000
|
||||
LOG.debug("vm total=%s" % (mem_alloc))
|
||||
|
||||
avs_hp_size = rpc_port['avs_hugepages_size_mib']
|
||||
avs_hp_nr = rpc_port['avs_hugepages_nr']
|
||||
mem_alloc += avs_hp_size * avs_hp_nr
|
||||
LOG.debug("avs_hp_nr=%s avs_hp_size=%s" % (avs_hp_nr, avs_hp_size))
|
||||
vs_hp_size = rpc_port['vswitch_hugepages_size_mib']
|
||||
vs_hp_nr = rpc_port['vswitch_hugepages_nr']
|
||||
mem_alloc += vs_hp_size * vs_hp_nr
|
||||
LOG.debug("vs_hp_nr=%s vs_hp_size=%s" % (vs_hp_nr, vs_hp_size))
|
||||
LOG.debug("memTotal %s mem_alloc %s" % (node_memtotal_mib, mem_alloc))
|
||||
|
||||
# Initial configuration defaults mem_alloc to consume 100% of 2M pages,
|
||||
|
@ -117,7 +117,7 @@ class Port(base.APIBase):
|
||||
"Represent the interface_id the port belongs to"
|
||||
|
||||
dpdksupport = bool
|
||||
"Represent whether or not the port supported AVS acceleration"
|
||||
"Represent whether or not the port supports DPDK acceleration"
|
||||
|
||||
host_uuid = types.uuid
|
||||
"Represent the UUID of the host the port belongs to"
|
||||
|
@ -48,6 +48,8 @@ from sysinv.openstack.common.gettextutils import _
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
VALID_VSWITCH_TYPES = [constants.VSWITCH_TYPE_OVS_DPDK]
|
||||
|
||||
|
||||
class System(base.APIBase):
|
||||
"""API representation of a system.
|
||||
@ -353,6 +355,8 @@ class SystemController(rest.RestController):
|
||||
change_https = False
|
||||
change_sdn = False
|
||||
change_dc_role = False
|
||||
vswitch_type = None
|
||||
|
||||
# prevent description field from being updated
|
||||
for p in jsonpatch.JsonPatch(patch):
|
||||
if p['path'] == '/software_version':
|
||||
@ -412,6 +416,10 @@ class SystemController(rest.RestController):
|
||||
distributed_cloud_role = p['value']
|
||||
patch.remove(p)
|
||||
|
||||
if p['path'] == '/vswitch_type':
|
||||
vswitch_type = p['value']
|
||||
patch.remove(p)
|
||||
|
||||
try:
|
||||
patched_system = jsonpatch.apply_patch(system_dict,
|
||||
jsonpatch.JsonPatch(patch))
|
||||
@ -454,6 +462,15 @@ class SystemController(rest.RestController):
|
||||
raise wsme.exc.ClientSideError(_("distributed_cloud_role is already set "
|
||||
" as %s" % rpc_isystem['distributed_cloud_role']))
|
||||
|
||||
if 'vswitch_type' in updates:
|
||||
if vswitch_type not in VALID_VSWITCH_TYPES:
|
||||
raise wsme.exc.ClientSideError(_("unsupported vswitch_type: %s"
|
||||
% vswitch_type))
|
||||
if vswitch_type == rpc_isystem['capabilities']['vswitch_type']:
|
||||
raise wsme.exc.ClientSideError(_("vswitch_type is already set"
|
||||
" as %s" % vswitch_type))
|
||||
patched_system['capabilities']['vswitch_type'] = vswitch_type
|
||||
|
||||
# Update only the fields that have changed
|
||||
name = ""
|
||||
contact = ""
|
||||
@ -502,12 +519,16 @@ class SystemController(rest.RestController):
|
||||
pecan.request.context)
|
||||
if capabilities:
|
||||
if change_sdn:
|
||||
LOG.info("update sdn capabilities to %s" % capabilities)
|
||||
LOG.info("update sdn to %s" % capabilities)
|
||||
pecan.request.rpcapi.update_sdn_enabled(pecan.request.context)
|
||||
if change_https:
|
||||
LOG.info("update capabilities / https to %s" % capabilities)
|
||||
LOG.info("update https to %s" % capabilities)
|
||||
pecan.request.rpcapi.configure_system_https(
|
||||
pecan.request.context)
|
||||
if vswitch_type:
|
||||
LOG.info("update vswitch_type to %s" % capabilities)
|
||||
pecan.request.rpcapi.update_vswitch_type(
|
||||
pecan.request.context)
|
||||
|
||||
if distributed_cloud_role and change_dc_role:
|
||||
LOG.info("update distributed cloud role to %s" % distributed_cloud_role)
|
||||
|
@ -248,17 +248,9 @@ def is_aio_simplex_host_unlocked(host):
|
||||
host['invprovision'] != constants.PROVISIONING)
|
||||
|
||||
|
||||
# cache the result of the vswitch type to avoid having to query the system
|
||||
# for each access to this system attribute
|
||||
_vswitch_type = None
|
||||
|
||||
|
||||
def get_vswitch_type():
|
||||
global _vswitch_type
|
||||
if _vswitch_type is None:
|
||||
system = pecan.request.dbapi.isystem_get_one()
|
||||
_vswitch_type = system.capabilities.get('vswitch_type')
|
||||
return _vswitch_type
|
||||
system = pecan.request.dbapi.isystem_get_one()
|
||||
return system.capabilities.get('vswitch_type')
|
||||
|
||||
|
||||
def get_https_enabled():
|
||||
|
61
sysinv/sysinv/sysinv/sysinv/cmd/query_pci_id
Executable file
61
sysinv/sysinv/sysinv/sysinv/cmd/query_pci_id
Executable file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
from argparse import ArgumentParser
|
||||
|
||||
|
||||
def main():
|
||||
''' The goal of this script is to discover if the supplied PCI device is
|
||||
supported by the vswitch as an accelerated NIC.'''
|
||||
|
||||
parser = ArgumentParser(description="Query vswitch NIC support")
|
||||
|
||||
parser.add_argument("-v", "--vendor", dest="vid",
|
||||
help="Vendor ID",
|
||||
type=lambda x: hex(int(x, 0)),
|
||||
action='store', metavar="HEX",
|
||||
required=True)
|
||||
parser.add_argument("-d", "--device", dest="did",
|
||||
help="Device ID",
|
||||
type=lambda x: hex(int(x, 0)),
|
||||
action='store', metavar="HEX",
|
||||
required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
cmd = 'python /usr/share/openvswitch/scripts/dpdk-pmdinfo.py ' \
|
||||
'-r /usr/sbin/ovs-vswitchd'
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
|
||||
out, err = p.communicate()
|
||||
result = out.split('\n')
|
||||
|
||||
for line in result:
|
||||
if not line:
|
||||
continue
|
||||
|
||||
pmd_info = json.loads(line)
|
||||
supported_devices = pmd_info['pci_ids']
|
||||
|
||||
for supported_device in supported_devices:
|
||||
vid = hex(supported_device[0])
|
||||
did = hex(supported_device[1])
|
||||
|
||||
if vid == args.vid and did == args.did:
|
||||
print("Vendor ID: %s Device ID: %s is supported" %
|
||||
(args.vid, args.did))
|
||||
return 0
|
||||
|
||||
print("Vendor ID: %s Device ID: %s is not supported" %
|
||||
(args.vid, args.did))
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret = main()
|
||||
sys.exit(ret)
|
@ -244,7 +244,7 @@ NEUTRON_PROVIDERNET_VXLAN = "vxlan"
|
||||
NEUTRON_PROVIDERNET_VLAN = "vlan"
|
||||
|
||||
# Supported compute node vswitch types
|
||||
VSWITCH_TYPE_AVS = "avs"
|
||||
VSWITCH_TYPE_OVS_DPDK = "ovs-dpdk"
|
||||
VSWITCH_TYPE_NUAGE_VRS = "nuage_vrs"
|
||||
|
||||
# Partition default sizes
|
||||
|
@ -1744,7 +1744,7 @@ class ConductorManager(service.PeriodicService):
|
||||
mtu = constants.DEFAULT_MTU
|
||||
port = None
|
||||
# ignore port if no MAC address present, this will
|
||||
# occur for data port after they are configured via AVS
|
||||
# occur for data port after they are configured via DPDK driver
|
||||
if not inic['mac']:
|
||||
continue
|
||||
try:
|
||||
@ -6645,11 +6645,6 @@ class ConductorManager(service.PeriodicService):
|
||||
|
||||
# Apply Neutron manifest on Controller(this
|
||||
# will update the SNAT rules for the SDN controllers)
|
||||
# Ideally we would also like to apply the vswitch manifest
|
||||
# on Compute so as to write the vswitch.ini however AVS
|
||||
# cannot resync on the fly, so mark the Compute node as
|
||||
# config-out-of-date
|
||||
|
||||
self._config_update_hosts(context, [constants.COMPUTE], reboot=True)
|
||||
|
||||
config_uuid = self._config_update_hosts(context,
|
||||
@ -6679,6 +6674,30 @@ class ConductorManager(service.PeriodicService):
|
||||
personalities = [constants.COMPUTE]
|
||||
self._config_update_hosts(context, personalities, reboot=True)
|
||||
|
||||
def update_vswitch_type(self, context):
|
||||
"""Update the system vswitch type.
|
||||
|
||||
:param context: an admin context.
|
||||
"""
|
||||
LOG.info("update_vswitch_type")
|
||||
|
||||
personalities = [constants.CONTROLLER]
|
||||
config_dict = {
|
||||
"personalities": personalities,
|
||||
"classes": ['platform::sysctl::controller::runtime',
|
||||
'platform::nfv::runtime',
|
||||
'openstack::neutron::server::runtime']
|
||||
}
|
||||
config_uuid = self._config_update_hosts(context, personalities)
|
||||
self._config_apply_runtime_manifest(context, config_uuid, config_dict)
|
||||
|
||||
if tsc.system_type == constants.TIS_AIO_BUILD:
|
||||
personalities = [constants.CONTROLLER]
|
||||
else:
|
||||
personalities = [constants.COMPUTE]
|
||||
|
||||
self._config_update_hosts(context, personalities, reboot=True)
|
||||
|
||||
def _update_hosts_file(self, hostname, address, active=True):
|
||||
"""Update or add an entry to the /etc/hosts configuration file
|
||||
|
||||
|
@ -1226,6 +1226,14 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
|
||||
return self.call(context,
|
||||
self.make_msg('update_sdn_enabled'))
|
||||
|
||||
def update_vswitch_type(self, context):
|
||||
"""Synchronously, have the conductor update the system vswitch type
|
||||
|
||||
:param context: request context.
|
||||
"""
|
||||
return self.call(context,
|
||||
self.make_msg('update_vswitch_type'))
|
||||
|
||||
def configure_keystore_account(self, context, service_name,
|
||||
username, password):
|
||||
"""Synchronously, have a conductor configure a ks(keyring) account.
|
||||
|
@ -0,0 +1,29 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
#
|
||||
# Copyright (c) 2013-2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from sqlalchemy import MetaData, Table
|
||||
|
||||
ENGINE = 'InnoDB'
|
||||
CHARSET = 'utf8'
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
memory = Table('i_imemory', meta, autoload=True)
|
||||
memory.c.avs_hugepages_size_mib.alter(name="vswitch_hugepages_size_mib")
|
||||
memory.c.avs_hugepages_reqd.alter(name="vswitch_hugepages_reqd")
|
||||
memory.c.avs_hugepages_nr.alter(name="vswitch_hugepages_nr")
|
||||
memory.c.avs_hugepages_avail.alter(name="vswitch_hugepages_avail")
|
||||
return True
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
# As per other openstack components, downgrade is
|
||||
# unsupported in this release.
|
||||
raise NotImplementedError('SysInv database downgrade is unsupported.')
|
@ -293,10 +293,10 @@ class imemory(Base):
|
||||
|
||||
hugepages_configured = Column(Boolean, default=False)
|
||||
|
||||
avs_hugepages_size_mib = Column(Integer)
|
||||
avs_hugepages_reqd = Column(Integer)
|
||||
avs_hugepages_nr = Column(Integer)
|
||||
avs_hugepages_avail = Column(Integer)
|
||||
vswitch_hugepages_size_mib = Column(Integer)
|
||||
vswitch_hugepages_reqd = Column(Integer)
|
||||
vswitch_hugepages_nr = Column(Integer)
|
||||
vswitch_hugepages_avail = Column(Integer)
|
||||
|
||||
vm_hugepages_nr_2M_pending = Column(Integer)
|
||||
vm_hugepages_nr_1G_pending = Column(Integer)
|
||||
|
@ -34,10 +34,10 @@ class Memory(base.SysinvObject):
|
||||
|
||||
'hugepages_configured': utils.str_or_none,
|
||||
|
||||
'avs_hugepages_size_mib': utils.int_or_none,
|
||||
'avs_hugepages_reqd': utils.int_or_none,
|
||||
'avs_hugepages_nr': utils.int_or_none,
|
||||
'avs_hugepages_avail': utils.int_or_none,
|
||||
'vswitch_hugepages_size_mib': utils.int_or_none,
|
||||
'vswitch_hugepages_reqd': utils.int_or_none,
|
||||
'vswitch_hugepages_nr': utils.int_or_none,
|
||||
'vswitch_hugepages_avail': utils.int_or_none,
|
||||
|
||||
'vm_hugepages_nr_2M_pending': utils.int_or_none,
|
||||
'vm_hugepages_nr_1G_pending': utils.int_or_none,
|
||||
|
@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
class quoted_str(str):
|
||||
pass
|
||||
|
||||
|
||||
# force strings to be single-quoted to avoid interpretation as numeric values
|
||||
def quoted_presenter(dumper, data):
|
||||
return dumper.represent_scalar(u'tag:yaml.org,2002:str', data, style="'")
|
||||
|
||||
|
||||
yaml.add_representer(quoted_str, quoted_presenter)
|
@ -16,6 +16,8 @@ from sysinv.common import constants
|
||||
from sysinv.common import utils
|
||||
from sysinv.common import exception
|
||||
|
||||
from . import quoted_str
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class BasePuppet(object):
|
||||
@ -45,6 +47,10 @@ class BasePuppet(object):
|
||||
def context(self):
|
||||
return self._operator.context
|
||||
|
||||
@staticmethod
|
||||
def quoted_str(value):
|
||||
return quoted_str(value)
|
||||
|
||||
@staticmethod
|
||||
def _generate_random_password(length=16):
|
||||
suffix = "Ti0*"
|
||||
@ -79,6 +85,13 @@ class BasePuppet(object):
|
||||
system = self._get_system()
|
||||
return system.capabilities.get('region_config', False)
|
||||
|
||||
def _vswitch_type(self):
|
||||
if self.dbapi is None:
|
||||
return False
|
||||
|
||||
system = self._get_system()
|
||||
return system.capabilities.get('vswitch_type', None)
|
||||
|
||||
def _distributed_cloud_role(self):
|
||||
if self.dbapi is None:
|
||||
return None
|
||||
@ -160,6 +173,14 @@ class BasePuppet(object):
|
||||
cpus.append(c)
|
||||
return cpus
|
||||
|
||||
def _get_vswitch_cpu_list(self, host):
|
||||
cpus = self._get_host_cpu_list(host, constants.VSWITCH_FUNCTION)
|
||||
return sorted(cpus, key=lambda c: c.cpu)
|
||||
|
||||
def _get_platform_cpu_list(self, host):
|
||||
cpus = self._get_host_cpu_list(host, constants.PLATFORM_FUNCTION)
|
||||
return sorted(cpus, key=lambda c: c.cpu)
|
||||
|
||||
def _get_service_parameters(self, service=None):
|
||||
service_parameters = []
|
||||
if self.dbapi is None:
|
||||
|
@ -12,18 +12,16 @@ import uuid
|
||||
from netaddr import IPAddress
|
||||
from netaddr import IPNetwork
|
||||
|
||||
from netaddr import EUI
|
||||
from netaddr import mac_unix
|
||||
|
||||
from sysinv.common import constants
|
||||
from sysinv.common import exception
|
||||
from sysinv.common import utils
|
||||
from sysinv.conductor import openstack
|
||||
from sysinv.openstack.common import log
|
||||
|
||||
from . import base
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
MAC_ADDRESS_UL_BIT_VALUE = 2
|
||||
|
||||
PLATFORM_NETWORK_TYPES = [constants.NETWORK_TYPE_PXEBOOT,
|
||||
constants.NETWORK_TYPE_MGMT,
|
||||
@ -59,6 +57,16 @@ ADDRESS_CONFIG_RESOURCE = 'platform::addresses::address_config'
|
||||
class InterfacePuppet(base.BasePuppet):
|
||||
"""Class to encapsulate puppet operations for interface configuration"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(InterfacePuppet, self).__init__(*args, **kwargs)
|
||||
self._openstack = None
|
||||
|
||||
@property
|
||||
def openstack(self):
|
||||
if not self._openstack:
|
||||
self._openstack = openstack.OpenStackOperator(self.dbapi)
|
||||
return self._openstack
|
||||
|
||||
def get_host_config(self, host):
|
||||
"""
|
||||
Generate the hiera data for the puppet network config and route config
|
||||
@ -125,7 +133,7 @@ class InterfacePuppet(base.BasePuppet):
|
||||
'networks': self._get_network_type_index(),
|
||||
'gateways': self._get_gateway_index(),
|
||||
'floatingips': self._get_floating_ip_index(),
|
||||
'providernets': {},
|
||||
'providernets': self._get_provider_networks(host),
|
||||
}
|
||||
return context
|
||||
|
||||
@ -306,6 +314,18 @@ class InterfacePuppet(base.BasePuppet):
|
||||
|
||||
return floating_ips
|
||||
|
||||
def _get_provider_networks(self, host):
|
||||
# TODO(alegacy): this will not work as intended for upgrades of AIO-SX
|
||||
# and -DX. The call to get_providernetworksdict will return an empty
|
||||
# dictionary because the neutron endpoint is not available yet. Since
|
||||
# we do not currently support SDN/OVS over upgrades we will need to
|
||||
# deal with this in a later commit.
|
||||
pnets = {}
|
||||
if (self.openstack and
|
||||
constants.COMPUTE in utils.get_personalities(host)):
|
||||
pnets = self.openstack.get_providernetworksdict(quiet=True)
|
||||
return pnets
|
||||
|
||||
|
||||
def is_platform_network_type(iface):
|
||||
networktype = utils.get_primary_network_type(iface)
|
||||
@ -733,7 +753,7 @@ def needs_interface_config(context, iface):
|
||||
if is_a_mellanox_device(context, iface):
|
||||
# Check for Mellanox data interfaces. We must set the MTU sizes of
|
||||
# Mellanox data interfaces in case it is not the default. Normally
|
||||
# data interfaces are owned by AVS, they are not managed through
|
||||
# data interfaces are owned by DPDK, they are not managed through
|
||||
# Linux but in the Mellanox case, the interfaces are still visible
|
||||
# in Linux so in case one needs to set jumbo frames, it has to be
|
||||
# set in Linux as well. We only do this for combined nodes or
|
||||
@ -744,21 +764,6 @@ def needs_interface_config(context, iface):
|
||||
return False
|
||||
|
||||
|
||||
def needs_vswitch_config(context, iface):
|
||||
"""
|
||||
Determine whether an interface needs to be configured as a vswitch
|
||||
interface. This is true if the interface is a data interface, is required
|
||||
by a platform interface (i.e., a platform VLAN over a data interface), is
|
||||
required by a data interface (i.e., a data AE member, a VLAN lower
|
||||
interface).
|
||||
"""
|
||||
if not is_compute_subfunction(context):
|
||||
return False
|
||||
elif is_data_interface(context, iface):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_basic_network_config(ifname, ensure='present',
|
||||
method='manual', onboot='true',
|
||||
hotplug='false', family='inet',
|
||||
@ -1001,167 +1006,6 @@ def generate_network_config(context, config, iface):
|
||||
})
|
||||
|
||||
|
||||
class CustomMacDialect(mac_unix):
|
||||
word_fmt = '%.2x'
|
||||
|
||||
|
||||
def _set_local_admin_bit(value):
|
||||
"""
|
||||
Assert the locally administered bit in the MAC address in order to avoid
|
||||
conflicting with the real port that this interface is associated with.
|
||||
"""
|
||||
mac = EUI(value, dialect=CustomMacDialect)
|
||||
mac.__setitem__(0, (mac.words[0] | MAC_ADDRESS_UL_BIT_VALUE))
|
||||
return str(mac)
|
||||
|
||||
|
||||
def get_vswitch_ethernet_command(context, iface):
|
||||
"""
|
||||
Produce the cli command to add a single ethernet interface to vswitch.
|
||||
"""
|
||||
port = get_interface_port(context, iface)
|
||||
attributes = {'ifname': get_interface_os_ifname(context, iface) + '-avp',
|
||||
'port_uuid': port['uuid'],
|
||||
'iface_uuid': iface['uuid'],
|
||||
'mtu': iface['imtu']}
|
||||
if is_dpdk_compatible(context, iface):
|
||||
command = ("ethernet add %(port_uuid)s %(iface_uuid)s "
|
||||
"%(mtu)s\n" % attributes)
|
||||
else:
|
||||
# Set the locally administered bit on the MAC address because to run
|
||||
# providernet connectivity tests we will need to originate packets from
|
||||
# this interface. Since the other end of the interface is the actual
|
||||
# avp interface in the linux kernel it will get confused if we are
|
||||
# sending it packets originated from its' MAC address.
|
||||
attributes.update({'mac': _set_local_admin_bit(iface['imac']),
|
||||
'numa': 0})
|
||||
command = ("port add avp-provider %(iface_uuid)s %(mac)s %(numa)s "
|
||||
"%(mtu)s %(ifname)s\n" % attributes)
|
||||
return command
|
||||
|
||||
|
||||
def get_vswitch_vlan_command(context, iface):
|
||||
"""
|
||||
Produce the cli command to add a vlan ethernet interface to vswitch.
|
||||
"""
|
||||
lower_iface = get_lower_interface(context, iface)
|
||||
attributes = {'lower_uuid': lower_iface['uuid'],
|
||||
'vlan_id': iface['vlan_id'],
|
||||
'iface_uuid': iface['uuid'],
|
||||
'mtu': iface['imtu']}
|
||||
command = ("vlan add %(lower_uuid)s %(vlan_id)s %(iface_uuid)s %(mtu)s" %
|
||||
attributes)
|
||||
if is_platform_interface(context, iface):
|
||||
# If this is a platform VLAN than mark it as a host interface to
|
||||
# prevent the vswitch bridge input handler from intercepting packets
|
||||
# destined to the interface MAC. That intercept exists for providernet
|
||||
# connectivity tests but those are not necessary on platform VLAN
|
||||
# interfaces.
|
||||
command += " host"
|
||||
return command + "\n"
|
||||
|
||||
|
||||
def get_vswitch_bond_options(iface):
|
||||
"""
|
||||
Return a dictionary of vswitch bond attributes based on the interface
|
||||
configuration.
|
||||
"""
|
||||
monitor_mode = 'link-state'
|
||||
|
||||
ae_mode = iface['aemode']
|
||||
if ae_mode in BALANCED_AE_MODES:
|
||||
distribution_mode = 'hash-mac'
|
||||
protection_mode = 'loadbalance'
|
||||
elif ae_mode in LACP_AE_MODES:
|
||||
distribution_mode = 'hash-mac'
|
||||
protection_mode = '802.3ad'
|
||||
else:
|
||||
protection_mode = 'failover'
|
||||
distribution_mode = 'none'
|
||||
|
||||
return {'distribution': distribution_mode,
|
||||
'protection': protection_mode,
|
||||
'monitor': monitor_mode}
|
||||
|
||||
|
||||
def get_vswitch_bond_commands(context, iface):
|
||||
"""
|
||||
Produce the cli command to add a aggregated ethernet interface to vswitch.
|
||||
"""
|
||||
|
||||
attributes = {'uuid': iface['uuid'],
|
||||
'mtu': iface['imtu']}
|
||||
attributes.update(get_vswitch_bond_options(iface))
|
||||
|
||||
# Setup the AE interface
|
||||
commands = ("ae add %(uuid)s %(mtu)s %(protection)s %(distribution)s "
|
||||
"%(monitor)s\n" % attributes)
|
||||
|
||||
# Add all lower interfaces as AE member interfaces
|
||||
for lower_ifname in iface['uses']:
|
||||
lower_iface = context['interfaces'][lower_ifname]
|
||||
commands += ("ae attach member %s %s\n" %
|
||||
(iface['uuid'], lower_iface['uuid']))
|
||||
|
||||
return commands
|
||||
|
||||
|
||||
def get_vswitch_interface_commands(context, iface):
|
||||
"""
|
||||
Produce the cli command to add a single interface to vswitch.
|
||||
"""
|
||||
if iface['iftype'] == constants.INTERFACE_TYPE_ETHERNET:
|
||||
return get_vswitch_ethernet_command(context, iface)
|
||||
elif iface['iftype'] == constants.INTERFACE_TYPE_AE:
|
||||
return get_vswitch_bond_commands(context, iface)
|
||||
elif iface['iftype'] == constants.INTERFACE_TYPE_VLAN:
|
||||
return get_vswitch_vlan_command(context, iface)
|
||||
|
||||
|
||||
def get_vswitch_address_command(iface, address):
|
||||
"""
|
||||
Produce the cli command required to create an interface address.
|
||||
"""
|
||||
attributes = {'iface_uuid': iface['uuid'],
|
||||
'address': address['address'],
|
||||
'prefix': address['prefix']}
|
||||
return ('interface add addr %(iface_uuid)s %(address)s/%(prefix)s\n' %
|
||||
attributes)
|
||||
|
||||
|
||||
def get_vswitch_route_command(iface, route):
|
||||
"""
|
||||
Produce the vswitch cli command required to create a route table entry for
|
||||
a given interface.
|
||||
"""
|
||||
attributes = {'iface_uuid': iface['uuid'],
|
||||
'network': route['network'],
|
||||
'prefix': route['prefix'],
|
||||
'gateway': route['gateway'],
|
||||
'metric': route['metric']}
|
||||
return ('route append %(network)s/%(prefix)s %(iface_uuid)s %(gateway)s '
|
||||
'%(metric)s\n' % attributes)
|
||||
|
||||
|
||||
def get_vswitch_commands(context, iface):
|
||||
"""
|
||||
Produce the vswitch cli commands required for configuring the logical
|
||||
interfaces in vswitch for this particular interface.
|
||||
"""
|
||||
commands = get_vswitch_interface_commands(context, iface)
|
||||
|
||||
networktype = utils.get_primary_network_type(iface)
|
||||
if networktype in DATA_NETWORK_TYPES:
|
||||
# Add complementary commands (if needed)
|
||||
for address in context['addresses'].get(iface['ifname'], []):
|
||||
if address['networktype'] == networktype:
|
||||
commands += get_vswitch_address_command(iface, address)
|
||||
for route in context['routes'].get(iface['ifname'], []):
|
||||
commands += get_vswitch_route_command(iface, route)
|
||||
|
||||
return commands
|
||||
|
||||
|
||||
def find_interface_by_type(context, networktype):
|
||||
"""
|
||||
Lookup an interface based on networktype. This is only intended for
|
||||
|
@ -65,8 +65,6 @@ class NeutronPuppet(openstack.OpenstackBasePuppet):
|
||||
|
||||
ksuser = self._get_service_user_name(self.SERVICE_NAME)
|
||||
|
||||
sdn_l3_mode_enabled = self._get_sdn_l3_mode_enabled()
|
||||
|
||||
config = {
|
||||
'neutron::server::notifications::auth_url':
|
||||
self._keystone_identity_uri(),
|
||||
@ -85,8 +83,6 @@ class NeutronPuppet(openstack.OpenstackBasePuppet):
|
||||
|
||||
'neutron::agents::metadata::metadata_ip':
|
||||
self._get_management_address(),
|
||||
'neutron::agents::vswitch::sdn_manage_external_networks':
|
||||
not sdn_l3_mode_enabled,
|
||||
|
||||
'neutron::keystone::authtoken::auth_url':
|
||||
self._keystone_identity_uri(),
|
||||
@ -113,8 +109,6 @@ class NeutronPuppet(openstack.OpenstackBasePuppet):
|
||||
|
||||
'openstack::neutron::params::region_name':
|
||||
self.get_region_name(),
|
||||
'openstack::neutron::params::l3_agent_enabled':
|
||||
not sdn_l3_mode_enabled,
|
||||
'openstack::neutron::params::service_create':
|
||||
self._to_create_services(),
|
||||
}
|
||||
@ -163,33 +157,19 @@ class NeutronPuppet(openstack.OpenstackBasePuppet):
|
||||
controller_config
|
||||
}
|
||||
|
||||
def _get_sdn_l3_mode_enabled(self):
|
||||
try:
|
||||
sdn_l3_mode = self.dbapi.service_parameter_get_one(
|
||||
service=constants.SERVICE_TYPE_NETWORK,
|
||||
section=constants.SERVICE_PARAM_SECTION_NETWORK_DEFAULT,
|
||||
name=constants.SERVICE_PARAM_NAME_DEFAULT_SERVICE_PLUGINS)
|
||||
if not sdn_l3_mode:
|
||||
return False
|
||||
allowed_vals = constants.SERVICE_PLUGINS_SDN
|
||||
return (any(sp in allowed_vals
|
||||
for sp in sdn_l3_mode.value.split(',')))
|
||||
except:
|
||||
return False
|
||||
|
||||
def get_host_config(self, host):
|
||||
interface_mappings = []
|
||||
device_mappings = []
|
||||
for iface in self.context['interfaces'].values():
|
||||
if (utils.get_primary_network_type(iface) ==
|
||||
constants.NETWORK_TYPE_PCI_SRIOV):
|
||||
port = interface.get_interface_port(self.context, iface)
|
||||
providernets = interface.get_interface_providernets(iface)
|
||||
for net in providernets:
|
||||
interface_mappings.append("%s:%s" % (net, port['name']))
|
||||
device_mappings.append("%s:%s" % (net, port['name']))
|
||||
|
||||
config = {
|
||||
'neutron::agents::ml2::sriov::physical_device_mappings':
|
||||
interface_mappings,
|
||||
device_mappings,
|
||||
}
|
||||
|
||||
if host.personality == constants.CONTROLLER:
|
||||
|
@ -26,11 +26,9 @@ class NfvPuppet(openstack.OpenstackBasePuppet):
|
||||
system = self._get_system()
|
||||
|
||||
if system.system_mode == constants.SYSTEM_MODE_SIMPLEX:
|
||||
data_port_fault_handling_enabled = False
|
||||
single_hypervisor = True
|
||||
single_controller = True
|
||||
else:
|
||||
data_port_fault_handling_enabled = True
|
||||
single_hypervisor = False
|
||||
single_controller = False
|
||||
|
||||
@ -52,8 +50,6 @@ class NfvPuppet(openstack.OpenstackBasePuppet):
|
||||
self._get_management_address(),
|
||||
'nfv::nfvi::host_listener_host':
|
||||
self._get_management_address(),
|
||||
'nfv::nfvi::infrastructure_rest_api_data_port_fault_handling_enabled':
|
||||
data_port_fault_handling_enabled,
|
||||
|
||||
'nfv::nfvi::openstack_username':
|
||||
self._operator.keystone.get_admin_user_name(),
|
||||
|
277
sysinv/sysinv/sysinv/sysinv/puppet/ovs.py
Normal file
277
sysinv/sysinv/sysinv/sysinv/puppet/ovs.py
Normal file
@ -0,0 +1,277 @@
|
||||
#
|
||||
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from sysinv.common import constants
|
||||
from sysinv.common import utils
|
||||
|
||||
from . import base
|
||||
from . import interface
|
||||
|
||||
|
||||
class OVSPuppet(base.BasePuppet):
|
||||
"""Class to encapsulate puppet operations for vswitch configuration"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OVSPuppet, self).__init__(*args, **kwargs)
|
||||
|
||||
def get_host_config(self, host):
|
||||
config = {}
|
||||
if (constants.COMPUTE in utils.get_personalities(host) and
|
||||
self._vswitch_type() == constants.VSWITCH_TYPE_OVS_DPDK):
|
||||
config.update(self._get_cpu_config(host))
|
||||
config.update(self._get_memory_config(host))
|
||||
config.update(self._get_port_config(host))
|
||||
config.update(self._get_virtual_config(host))
|
||||
config.update(self._get_neutron_config(host))
|
||||
return config
|
||||
|
||||
def _get_port_config(self, host):
|
||||
ovs_devices = {}
|
||||
ovs_bridges = {}
|
||||
ovs_ports = {}
|
||||
ovs_addresses = {}
|
||||
|
||||
index = 0
|
||||
for iface in sorted(self.context['interfaces'].values(),
|
||||
key=interface.interface_sort_key):
|
||||
if interface.is_data_network_type(iface):
|
||||
# create a separate bridge for every configured data interface
|
||||
brname = 'br-phy%d' % index
|
||||
ovs_bridges[brname] = {}
|
||||
|
||||
# save the associated bridge for provider network mapping
|
||||
iface['_ovs_bridge'] = brname
|
||||
|
||||
if iface['iftype'] == constants.INTERFACE_TYPE_ETHERNET:
|
||||
port, devices = self._get_ethernet_port(
|
||||
host, iface, brname, index)
|
||||
elif iface['iftype'] == constants.INTERFACE_TYPE_AE:
|
||||
port, devices = self._get_bond_port(
|
||||
host, iface, brname, index)
|
||||
elif iface['iftype'] == constants.INTERFACE_TYPE_VLAN:
|
||||
port, devices = self._get_vlan_port(
|
||||
host, iface, brname, index)
|
||||
else:
|
||||
raise Exception("unsupported interface type: %s" %
|
||||
iface['iftype'])
|
||||
|
||||
ovs_ports.update({port['name']: port})
|
||||
ovs_devices.update({d['pci_addr']: d for d in devices})
|
||||
|
||||
index += 1
|
||||
|
||||
# currently only one provider network is supported per
|
||||
# interface, therefore obtain first entry
|
||||
providernet = interface.get_interface_providernets(iface)[0]
|
||||
|
||||
# setup tunnel address if assigned provider network is vxlan
|
||||
if self._is_vxlan_providernet(providernet):
|
||||
address = interface.get_interface_primary_address(
|
||||
self.context, iface)
|
||||
if address:
|
||||
ovs_addresses[brname] = {
|
||||
'ifname': brname,
|
||||
'address': address['address'],
|
||||
'prefixlen': address['prefix'],
|
||||
}
|
||||
|
||||
return {
|
||||
'platform::vswitch::ovs::devices': ovs_devices,
|
||||
'platform::vswitch::ovs::bridges': ovs_bridges,
|
||||
'platform::vswitch::ovs::ports': ovs_ports,
|
||||
'platform::vswitch::ovs::addresses': ovs_addresses,
|
||||
}
|
||||
|
||||
def _get_ethernet_device(self, iface):
|
||||
port = interface.get_interface_port(self.context, iface)
|
||||
|
||||
pci_addr = self.quoted_str(port.pciaddr)
|
||||
|
||||
return {
|
||||
'pci_addr': pci_addr
|
||||
}
|
||||
|
||||
def _get_ethernet_interface(self, host, iface, ifname):
|
||||
|
||||
port = interface.get_interface_port(self.context, iface)
|
||||
|
||||
rxq_count = len(self.context["_ovs_cpus"])
|
||||
|
||||
attributes = [
|
||||
"options:dpdk-devargs=%s" % str(port.pciaddr),
|
||||
"options:n_rxq=%d" % rxq_count,
|
||||
"mtu_request=%d" % iface['imtu']
|
||||
]
|
||||
|
||||
# TODO(mpeters): set other_config:pmd-rxq-affinity to pin receive
|
||||
# queues to specific PMD cores
|
||||
|
||||
iftype = 'dpdk'
|
||||
|
||||
return {
|
||||
'name': ifname,
|
||||
'type': iftype,
|
||||
'attributes': attributes,
|
||||
}
|
||||
|
||||
def _get_ethernet_port(self, host, iface, bridge, index):
|
||||
devices = []
|
||||
interfaces = []
|
||||
|
||||
ifname = 'eth%d' % index
|
||||
|
||||
devices.append(self._get_ethernet_device(iface))
|
||||
interfaces.append(self._get_ethernet_interface(host, iface, ifname))
|
||||
|
||||
port = {
|
||||
'name': ifname,
|
||||
'bridge': bridge,
|
||||
'interfaces': interfaces,
|
||||
}
|
||||
|
||||
return port, devices
|
||||
|
||||
def _get_bond_port(self, host, iface, bridge, index):
|
||||
devices = []
|
||||
interfaces = []
|
||||
attributes = []
|
||||
|
||||
ifname = 'bond%d' % index
|
||||
|
||||
# TODO(mpeters): OVS can support balance-tcp if interface txhashpolicy
|
||||
# is set to layer3+4 (currently restricted at API for data interfaces)
|
||||
ae_mode = iface['aemode']
|
||||
if ae_mode in interface.ACTIVE_STANDBY_AE_MODES:
|
||||
attributes.append("bond_mode=active-backup")
|
||||
if ae_mode in interface.BALANCED_AE_MODES:
|
||||
attributes.append("bond_mode=balance-slb")
|
||||
elif ae_mode in interface.LACP_AE_MODES:
|
||||
attributes.append("lacp=active")
|
||||
attributes.append("bond_mode=balance-slb")
|
||||
attributes.append("other_config:lacp-time=fast")
|
||||
|
||||
for member, lower_ifname in enumerate(iface['uses']):
|
||||
lower_iface = self.context['interfaces'][lower_ifname]
|
||||
member_ifname = '%s.%d' % (ifname, member)
|
||||
|
||||
devices.append(self._get_ethernet_device(lower_iface))
|
||||
interfaces.append(self._get_ethernet_interface(
|
||||
host, lower_iface, member_ifname))
|
||||
|
||||
port = {
|
||||
'type': 'bond',
|
||||
'name': ifname,
|
||||
'bridge': bridge,
|
||||
'attributes': attributes,
|
||||
'interfaces': interfaces,
|
||||
}
|
||||
|
||||
return port, devices
|
||||
|
||||
def _get_vlan_port(self, host, iface, bridge, index):
|
||||
devices = []
|
||||
interfaces = []
|
||||
|
||||
ifname = 'vlan%d' % iface['vlan_id']
|
||||
attributes = [
|
||||
"tag=%d" % iface['vlan_id']
|
||||
]
|
||||
|
||||
lower_iface = interface.get_lower_interface(self.context, iface)
|
||||
|
||||
devices.append(self._get_ethernet_device(lower_iface))
|
||||
interfaces.append(self._get_ethernet_interface(
|
||||
host, lower_iface, ifname))
|
||||
|
||||
port = {
|
||||
'name': ifname,
|
||||
'bridge': bridge,
|
||||
'attributes': attributes,
|
||||
'interfaces': interfaces,
|
||||
}
|
||||
|
||||
return port, devices
|
||||
|
||||
def _get_cpu_config(self, host):
|
||||
platform_cpus = self._get_platform_cpu_list(host)
|
||||
vswitch_cpus = self._get_vswitch_cpu_list(host)
|
||||
|
||||
host_cpus = platform_cpus[:1] + vswitch_cpus[:]
|
||||
|
||||
host_core_list = self.quoted_str(
|
||||
','.join([str(c.cpu) for c in host_cpus]))
|
||||
pmd_core_list = self.quoted_str(
|
||||
','.join([str(c.cpu) for c in vswitch_cpus]))
|
||||
|
||||
# save the assigned CPUs for port assignment
|
||||
self.context["_ovs_cpus"] = [c.cpu for c in vswitch_cpus]
|
||||
|
||||
return {
|
||||
'vswitch::dpdk::host_core_list': host_core_list,
|
||||
'vswitch::dpdk::pmd_core_list': pmd_core_list,
|
||||
}
|
||||
|
||||
def _get_memory_config(self, host):
|
||||
vswitch_memory = []
|
||||
|
||||
host_memory = self.dbapi.imemory_get_by_ihost(host.id)
|
||||
for memory in host_memory:
|
||||
vswitch_size = memory.vswitch_hugepages_size_mib
|
||||
vswitch_pages = memory.vswitch_hugepages_nr
|
||||
vswitch_memory.append(str(vswitch_size * vswitch_pages))
|
||||
|
||||
dpdk_socket_mem = self.quoted_str(','.join(vswitch_memory))
|
||||
|
||||
return {
|
||||
'vswitch::dpdk::socket_mem': dpdk_socket_mem
|
||||
}
|
||||
|
||||
def _get_virtual_config(self, host):
|
||||
config = {}
|
||||
if utils.is_virtual() or utils.is_virtual_compute(host):
|
||||
config.update({
|
||||
'platform::vswitch::params::iommu_enabled': False,
|
||||
'platform::vswitch::params::hugepage_dir': '/mnt/huge-2048kB',
|
||||
|
||||
'openstack::neutron::params::tunnel_csum': True,
|
||||
})
|
||||
return config
|
||||
|
||||
def _get_neutron_config(self, host):
|
||||
local_ip = None
|
||||
tunnel_types = set()
|
||||
bridge_mappings = []
|
||||
for iface in self.context['interfaces'].values():
|
||||
if interface.is_data_network_type(iface):
|
||||
# obtain the assigned bridge for interface
|
||||
brname = iface.get('_ovs_bridge')
|
||||
if brname:
|
||||
providernets = interface.get_interface_providernets(iface)
|
||||
for providernet in providernets:
|
||||
if self._is_vxlan_providernet(providernet):
|
||||
address = interface.get_interface_primary_address(
|
||||
self.context, iface)
|
||||
if address:
|
||||
local_ip = address['address']
|
||||
tunnel_types.add(
|
||||
constants.NEUTRON_PROVIDERNET_VXLAN)
|
||||
else:
|
||||
bridge_mappings.append('%s:%s' %
|
||||
(providernet, brname))
|
||||
|
||||
return {
|
||||
'neutron::agents::ml2::ovs::local_ip': local_ip,
|
||||
'neutron::agents::ml2::ovs::tunnel_types': list(tunnel_types),
|
||||
'neutron::agents::ml2::ovs::bridge_mappings': bridge_mappings
|
||||
}
|
||||
|
||||
def _get_providernet_type(self, name):
|
||||
if name in self.context['providernets']:
|
||||
return self.context['providernets'][name]['type']
|
||||
|
||||
def _is_vxlan_providernet(self, name):
|
||||
providernet_type = self._get_providernet_type(name)
|
||||
return bool(providernet_type == constants.NEUTRON_PROVIDERNET_VXLAN)
|
@ -89,6 +89,7 @@ class PlatformPuppet(base.BasePuppet):
|
||||
'platform::params::security_profile': system.security_profile,
|
||||
|
||||
'platform::config::params::timezone': system.timezone,
|
||||
'platform::params::vswitch_type': self._vswitch_type(),
|
||||
}
|
||||
|
||||
def _get_hosts_config(self):
|
||||
@ -586,12 +587,12 @@ class PlatformPuppet(base.BasePuppet):
|
||||
total_hugepages_2M = vm_hugepages_nr_2M
|
||||
total_hugepages_1G = vm_hugepages_nr_1G
|
||||
|
||||
if memory.avs_hugepages_size_mib == constants.MIB_2M:
|
||||
total_hugepages_2M += memory.avs_hugepages_nr
|
||||
vswitch_2M_page += memory.avs_hugepages_nr
|
||||
elif memory.avs_hugepages_size_mib == constants.MIB_1G:
|
||||
total_hugepages_1G += memory.avs_hugepages_nr
|
||||
vswitch_1G_page += memory.avs_hugepages_nr
|
||||
if memory.vswitch_hugepages_size_mib == constants.MIB_2M:
|
||||
total_hugepages_2M += memory.vswitch_hugepages_nr
|
||||
vswitch_2M_page += memory.vswitch_hugepages_nr
|
||||
elif memory.vswitch_hugepages_size_mib == constants.MIB_1G:
|
||||
total_hugepages_1G += memory.vswitch_hugepages_nr
|
||||
vswitch_1G_page += memory.vswitch_hugepages_nr
|
||||
|
||||
vswitch_2M_pages.append(vswitch_2M_page)
|
||||
vswitch_1G_pages.append(vswitch_1G_page)
|
||||
|
@ -40,6 +40,7 @@ from . import networking
|
||||
from . import neutron
|
||||
from . import nfv
|
||||
from . import nova
|
||||
from . import ovs
|
||||
from . import panko
|
||||
from . import patching
|
||||
from . import platform
|
||||
@ -89,6 +90,7 @@ class PuppetOperator(object):
|
||||
self.neutron = neutron.NeutronPuppet(self)
|
||||
self.nfv = nfv.NfvPuppet(self)
|
||||
self.nova = nova.NovaPuppet(self)
|
||||
self.ovs = ovs.OVSPuppet(self)
|
||||
self.panko = panko.PankoPuppet(self)
|
||||
self.patching = patching.PatchingPuppet(self)
|
||||
self.platform = platform.PlatformPuppet(self)
|
||||
@ -215,6 +217,7 @@ class PuppetOperator(object):
|
||||
config.update(self.panko.get_system_config())
|
||||
config.update(self.dcmanager.get_system_config())
|
||||
config.update(self.dcorch.get_system_config())
|
||||
# service_parameter must be last to permit overrides
|
||||
config.update(self.service_parameter.get_system_config())
|
||||
|
||||
filename = 'system.yaml'
|
||||
@ -274,6 +277,7 @@ class PuppetOperator(object):
|
||||
config = {}
|
||||
config.update(self.platform.get_host_config(host, config_uuid))
|
||||
config.update(self.interface.get_host_config(host))
|
||||
config.update(self.ovs.get_host_config(host))
|
||||
config.update(self.networking.get_host_config(host))
|
||||
config.update(self.storage.get_host_config(host))
|
||||
config.update(self.ldap.get_host_config(host))
|
||||
@ -283,6 +287,7 @@ class PuppetOperator(object):
|
||||
config.update(self.device.get_host_config(host))
|
||||
config.update(self.nova.get_host_config(host))
|
||||
config.update(self.neutron.get_host_config(host))
|
||||
# service_parameter must be last to permit overrides
|
||||
config.update(self.service_parameter.get_host_config(host))
|
||||
|
||||
self._write_host_config(host, config)
|
||||
@ -298,14 +303,16 @@ class PuppetOperator(object):
|
||||
config = {}
|
||||
config.update(self.platform.get_host_config(host, config_uuid))
|
||||
config.update(self.interface.get_host_config(host))
|
||||
config.update(self.ovs.get_host_config(host))
|
||||
config.update(self.networking.get_host_config(host))
|
||||
config.update(self.storage.get_host_config(host))
|
||||
config.update(self.ceph.get_host_config(host))
|
||||
config.update(self.device.get_host_config(host))
|
||||
config.update(self.nova.get_host_config(host))
|
||||
config.update(self.neutron.get_host_config(host))
|
||||
config.update(self.service_parameter.get_host_config(host))
|
||||
config.update(self.ldap.get_host_config(host))
|
||||
# service_parameter must be last to permit overrides
|
||||
config.update(self.service_parameter.get_host_config(host))
|
||||
|
||||
self._write_host_config(host, config)
|
||||
except Exception:
|
||||
@ -323,8 +330,9 @@ class PuppetOperator(object):
|
||||
config.update(self.networking.get_host_config(host))
|
||||
config.update(self.storage.get_host_config(host))
|
||||
config.update(self.ceph.get_host_config(host))
|
||||
config.update(self.service_parameter.get_host_config(host))
|
||||
config.update(self.ldap.get_host_config(host))
|
||||
# service_parameter must be last to permit overrides
|
||||
config.update(self.service_parameter.get_host_config(host))
|
||||
|
||||
self._write_host_config(host, config)
|
||||
except Exception:
|
||||
|
@ -1596,7 +1596,8 @@ class TestCpePost(InterfaceTestCase):
|
||||
|
||||
# Expected error: Unexpected interface network type list data
|
||||
@mock.patch.object(api_if_v1, '_neutron_providernet_extension_supported')
|
||||
def test_create_invalid_non_avs(self, mock_providernet_extension_supported):
|
||||
def test_create_invalid_non_vswitch(self,
|
||||
mock_providernet_extension_supported):
|
||||
mock_providernet_extension_supported.return_value = False
|
||||
self._create_ethernet('data0',
|
||||
networktype=constants.NETWORK_TYPE_DATA,
|
||||
|
@ -179,7 +179,8 @@ def get_test_isystem(**kw):
|
||||
'capabilities': kw.get('capabilities',
|
||||
{"cinder_backend":
|
||||
constants.CINDER_BACKEND_LVM,
|
||||
"vswitch_type": constants.VSWITCH_TYPE_AVS,
|
||||
"vswitch_type":
|
||||
constants.VSWITCH_TYPE_OVS_DPDK,
|
||||
"region_config": False,
|
||||
"sdn_enabled": True,
|
||||
"shared_services": "[]"}),
|
||||
@ -367,10 +368,10 @@ def get_test_imemory(**kw):
|
||||
|
||||
'hugepages_configured': kw.get('hugepages_configured', False),
|
||||
|
||||
'avs_hugepages_size_mib': kw.get('avs_hugepages_size_mib', 2),
|
||||
'avs_hugepages_reqd': kw.get('avs_hugepages_reqd'),
|
||||
'avs_hugepages_nr': kw.get('avs_hugepages_nr', 256),
|
||||
'avs_hugepages_avail': kw.get('avs_hugepages_avail', 0),
|
||||
'vswitch_hugepages_size_mib': kw.get('vswitch_hugepages_size_mib', 2),
|
||||
'vswitch_hugepages_reqd': kw.get('vswitch_hugepages_reqd'),
|
||||
'vswitch_hugepages_nr': kw.get('vswitch_hugepages_nr', 256),
|
||||
'vswitch_hugepages_avail': kw.get('vswitch_hugepages_avail', 0),
|
||||
|
||||
'vm_hugepages_nr_2M_pending': kw.get('vm_hugepages_nr_2M_pending'),
|
||||
'vm_hugepages_nr_1G_pending': kw.get('vm_hugepages_nr_1G_pending'),
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2017 Wind River Systems, Inc.
|
||||
# Copyright (c) 2017-2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -400,7 +400,11 @@ class BaseTestCase(dbbase.DbTestCase):
|
||||
|
||||
@puppet.puppet_context
|
||||
def _update_context(self):
|
||||
self.context = self.operator.interface._create_interface_context(self.host)
|
||||
self.context = \
|
||||
self.operator.interface._create_interface_context(self.host)
|
||||
|
||||
# Update the puppet context with generated interface context
|
||||
self.operator.context.update(self.context)
|
||||
|
||||
def _setup_context(self):
|
||||
self._setup_configuration()
|
||||
@ -1363,166 +1367,6 @@ class InterfaceTestCase(BaseTestCase):
|
||||
return port, iface
|
||||
|
||||
|
||||
class InterfaceVswitchTestCase(BaseTestCase):
|
||||
def _setup_configuration(self):
|
||||
# Create a single port/interface for basic function testing
|
||||
self._create_test_common()
|
||||
self._create_test_host(constants.COMPUTE)
|
||||
self.port, self.iface = (
|
||||
self._create_ethernet_test('data0',
|
||||
constants.NETWORK_TYPE_DATA))
|
||||
|
||||
def _update_context(self):
|
||||
# ensure DB entries are updated prior to updating the context which
|
||||
# will re-read the entries from the DB.
|
||||
self.host.save(self.admin_context)
|
||||
self.port.save(self.admin_context)
|
||||
self.iface.save(self.admin_context)
|
||||
super(InterfaceVswitchTestCase, self)._update_context()
|
||||
|
||||
def setUp(self):
|
||||
super(InterfaceVswitchTestCase, self).setUp()
|
||||
self._setup_context()
|
||||
|
||||
def test_needs_vswitch_config_false_on_controller(self):
|
||||
self.iface['networktype'] = constants.NETWORK_TYPE_DATA
|
||||
self.host['personality'] = constants.CONTROLLER
|
||||
self.host['subfunctions'] = constants.CONTROLLER
|
||||
self._update_context()
|
||||
needed = interface.needs_vswitch_config(self.context, self.iface)
|
||||
self.assertFalse(needed)
|
||||
|
||||
def test_needs_vswitch_config_true_on_compute(self):
|
||||
self.iface['networktype'] = constants.NETWORK_TYPE_DATA
|
||||
needed = interface.needs_vswitch_config(self.context, self.iface)
|
||||
self.assertTrue(needed)
|
||||
|
||||
def test_needs_vswitch_config_false_for_platform(self):
|
||||
vlan = self._create_vlan_test('infra0',
|
||||
constants.NETWORK_TYPE_INFRA, 1)
|
||||
self.host['personality'] = constants.COMPUTE
|
||||
self._update_context()
|
||||
needed = interface.needs_vswitch_config(self.context, vlan)
|
||||
self.assertFalse(needed)
|
||||
|
||||
def test_get_vswitch_ethernet_command(self):
|
||||
cmd = interface.get_vswitch_ethernet_command(self.context, self.iface)
|
||||
expected = ("ethernet add %(port_uuid)s %(iface_uuid)s %(mtu)s\n" %
|
||||
{'port_uuid': self.port['uuid'],
|
||||
'iface_uuid': self.iface['uuid'],
|
||||
'mtu': self.iface['imtu']})
|
||||
self.assertEqual(expected, cmd)
|
||||
|
||||
def test_get_vswitch_ethernet_command_slow_data(self):
|
||||
self.port['dpdksupport'] = False
|
||||
self._update_context()
|
||||
cmd = interface.get_vswitch_ethernet_command(self.context, self.iface)
|
||||
expected = (
|
||||
"port add avp-provider %(uuid)s %(mac)s 0 %(mtu)s %(ifname)s\n" %
|
||||
{'uuid': self.iface['uuid'],
|
||||
'mtu': self.iface['imtu'],
|
||||
'mac': interface._set_local_admin_bit(self.iface['imac']),
|
||||
'ifname': self.port['name'] + '-avp'})
|
||||
self.assertEqual(expected, cmd)
|
||||
|
||||
def test_get_vswitch_vlan_command(self):
|
||||
vlan = self._create_vlan_test(
|
||||
'data1', constants.NETWORK_TYPE_DATA, 1, self.iface)
|
||||
self._update_context()
|
||||
cmd = interface.get_vswitch_vlan_command(self.context, vlan)
|
||||
expected = ("vlan add %(lower_uuid)s %(vlan_id)s %(uuid)s %(mtu)s\n" %
|
||||
{'lower_uuid': self.iface['uuid'],
|
||||
'vlan_id': vlan['vlan_id'],
|
||||
'uuid': vlan['uuid'],
|
||||
'mtu': vlan['imtu']})
|
||||
self.assertEqual(expected, cmd)
|
||||
|
||||
def test_get_vswitch_vlan_command_for_platform(self):
|
||||
vlan = self._create_vlan_test(
|
||||
'infra', constants.NETWORK_TYPE_INFRA, 1, self.iface)
|
||||
self._update_context()
|
||||
cmd = interface.get_vswitch_vlan_command(self.context, vlan)
|
||||
expected = (
|
||||
"vlan add %(lower_uuid)s %(vlan_id)s %(uuid)s %(mtu)s host\n" %
|
||||
{'lower_uuid': self.iface['uuid'],
|
||||
'vlan_id': vlan['vlan_id'],
|
||||
'uuid': vlan['uuid'],
|
||||
'mtu': vlan['imtu']})
|
||||
self.assertEqual(expected, cmd)
|
||||
|
||||
def test_get_vswitch_address_command(self):
|
||||
address = self.context['addresses'].get(self.iface['ifname'])[0]
|
||||
cmd = interface.get_vswitch_address_command(self.iface, address)
|
||||
expected = (
|
||||
"interface add addr %(iface_uuid)s %(address)s/%(prefix)s\n" %
|
||||
{'iface_uuid': self.iface['uuid'],
|
||||
'address': address['address'],
|
||||
'prefix': address['prefix']})
|
||||
self.assertEqual(expected, cmd)
|
||||
|
||||
def test_get_vswitch_route_command(self):
|
||||
route = self.context['routes'].get(self.iface['ifname'])[0]
|
||||
cmd = interface.get_vswitch_route_command(self.iface, route)
|
||||
expected = (
|
||||
"route append %(network)s/%(prefix)s %(iface_uuid)s %(gateway)s "
|
||||
"%(metric)s\n" %
|
||||
{'iface_uuid': self.iface['uuid'],
|
||||
'network': route['network'],
|
||||
'gateway': route['gateway'],
|
||||
'prefix': route['prefix'],
|
||||
'metric': route['metric']})
|
||||
self.assertEqual(expected, cmd)
|
||||
|
||||
def test_get_vswitch_bond_options_balanced(self):
|
||||
bond = self._create_bond_test('data1', constants.NETWORK_TYPE_DATA)
|
||||
self._update_context()
|
||||
bond['aemode'] = 'balanced'
|
||||
options = interface.get_vswitch_bond_options(bond)
|
||||
expected = {'distribution': 'hash-mac',
|
||||
'protection': 'loadbalance',
|
||||
'monitor': 'link-state'}
|
||||
self.assertEqual(options, expected)
|
||||
|
||||
def test_get_vswitch_bond_options_8023ad(self):
|
||||
bond = self._create_bond_test('data1', constants.NETWORK_TYPE_DATA)
|
||||
self._update_context()
|
||||
bond['aemode'] = '802.3ad'
|
||||
options = interface.get_vswitch_bond_options(bond)
|
||||
expected = {'distribution': 'hash-mac',
|
||||
'protection': '802.3ad',
|
||||
'monitor': 'link-state'}
|
||||
self.assertEqual(options, expected)
|
||||
|
||||
def test_get_vswitch_bond_options_active_backup(self):
|
||||
bond = self._create_bond_test('data1', constants.NETWORK_TYPE_DATA)
|
||||
self._update_context()
|
||||
bond['aemode'] = 'active_backup'
|
||||
options = interface.get_vswitch_bond_options(bond)
|
||||
expected = {'distribution': 'none',
|
||||
'protection': 'failover',
|
||||
'monitor': 'link-state'}
|
||||
self.assertEqual(options, expected)
|
||||
|
||||
def test_get_vswitch_bond_commands(self):
|
||||
bond = self._create_bond_test('data1', constants.NETWORK_TYPE_DATA)
|
||||
self._update_context()
|
||||
bond['aemode'] = '802.3ad'
|
||||
options = interface.get_vswitch_bond_options(bond)
|
||||
attributes = {'uuid': bond['uuid'],
|
||||
'mtu': bond['imtu']}
|
||||
attributes.update(options)
|
||||
for index, lower_ifname in enumerate(bond['uses']):
|
||||
lower_iface = self.context['interfaces'][lower_ifname]
|
||||
attributes['member%s_uuid' % index] = lower_iface['uuid']
|
||||
expected = (
|
||||
"ae add %(uuid)s %(mtu)s %(protection)s %(distribution)s %(monitor)s\n"
|
||||
"ae attach member %(uuid)s %(member0_uuid)s\n"
|
||||
"ae attach member %(uuid)s %(member1_uuid)s\n" %
|
||||
attributes)
|
||||
cmds = interface.get_vswitch_bond_commands(self.context, bond)
|
||||
self.assertEqual(cmds, expected)
|
||||
|
||||
|
||||
class InterfaceHostTestCase(BaseTestCase):
|
||||
def _setup_configuration(self):
|
||||
# Personality is set to compute to avoid issues due to missing OAM
|
||||
@ -1558,27 +1402,13 @@ class InterfaceHostTestCase(BaseTestCase):
|
||||
class_name = self.__class__.__name__
|
||||
return os.path.join(hiera_directory, class_name) + ".yaml"
|
||||
|
||||
def _create_vswitch_directory(self):
|
||||
vswitch_path = os.path.join(os.environ['VIRTUAL_ENV'], 'vswitch')
|
||||
if not os.path.exists(vswitch_path):
|
||||
os.mkdir(vswitch_path, 0o755)
|
||||
return vswitch_path
|
||||
|
||||
def _get_vswitch_filename(self, vswitch_directory):
|
||||
class_name = self.__class__.__name__
|
||||
return os.path.join(vswitch_directory, class_name) + ".cmds"
|
||||
|
||||
def test_generate_interface_config(self):
|
||||
hieradata_directory = self._create_hieradata_directory()
|
||||
config_filename = self._get_config_filename(hieradata_directory)
|
||||
vswitch_directory = self._create_vswitch_directory()
|
||||
vswitch_filename = self._get_vswitch_filename(vswitch_directory)
|
||||
with open(config_filename, 'w') as config_file:
|
||||
config = self.operator.interface.get_host_config(self.host)
|
||||
self.assertIsNotNone(config)
|
||||
yaml.dump(config, config_file, default_flow_style=False)
|
||||
with open(vswitch_filename, 'w') as commands:
|
||||
commands.write(config['cgcs_vswitch::vswitch_commands'])
|
||||
|
||||
def test_create_interface_context(self):
|
||||
context = self.operator.interface._create_interface_context(self.host)
|
||||
@ -1612,7 +1442,7 @@ class InterfaceHostTestCase(BaseTestCase):
|
||||
for iface in self.interfaces:
|
||||
expected = bool(iface['ifname'] in self.expected_data_interfaces)
|
||||
if interface.is_data_interface(self.context, iface) != expected:
|
||||
print("iface %s is %sa vswitch interface" % (
|
||||
print("iface %s is %sa data interface" % (
|
||||
iface['ifname'], ('not ' if expected else '')))
|
||||
self.assertFalse(True)
|
||||
|
||||
@ -1676,19 +1506,6 @@ class InterfaceHostTestCase(BaseTestCase):
|
||||
iface['ifname'], ('not ' if expected else '')))
|
||||
self.assertFalse(True)
|
||||
|
||||
def test_needs_vswitch_config(self):
|
||||
expected_configured = []
|
||||
if interface.is_compute_subfunction(self.context):
|
||||
expected_configured += (self.expected_data_interfaces +
|
||||
self.expected_slow_interfaces)
|
||||
for iface in self.interfaces:
|
||||
expected = bool(iface['ifname'] in expected_configured)
|
||||
actual = interface.needs_vswitch_config(self.context, iface)
|
||||
if expected != actual:
|
||||
print("iface %s is %sconfigured" % (
|
||||
iface['ifname'], ('not ' if expected else '')))
|
||||
self.assertFalse(True)
|
||||
|
||||
|
||||
class InterfaceControllerEthernet(InterfaceHostTestCase):
|
||||
def _setup_configuration(self):
|
||||
|
@ -8,7 +8,6 @@ minversion = 1.6
|
||||
toxworkdir = /tmp/{env:USER}_sysinvtox
|
||||
wrsdir = {toxinidir}/../../../../../../../../..
|
||||
cgcsdir = {toxinidir}/../../../../..
|
||||
avsdir = {toxinidir}/../../../../../../../../wr-avs/layers/avs
|
||||
distshare={toxworkdir}/.tox/distshare
|
||||
|
||||
[testenv]
|
||||
|
Loading…
Reference in New Issue
Block a user