diff --git a/sysinv/sysinv/sysinv/sysinv/common/constants.py b/sysinv/sysinv/sysinv/sysinv/common/constants.py index 9ac1d40338..8b2c9d9f0e 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/constants.py +++ b/sysinv/sysinv/sysinv/sysinv/common/constants.py @@ -1483,6 +1483,7 @@ APP_TARFILE_NAME_PLACEHOLDER = 'tarfile-placeholder' CONTROL_PLANE_LABEL = 'openstack-control-plane=enabled' COMPUTE_NODE_LABEL = 'openstack-compute-node=enabled' OPENVSWITCH_LABEL = 'openvswitch=enabled' +SRIOV_LABEL = 'sriov=enabled' # Default DNS service domain DEFAULT_DNS_SERVICE_DOMAIN = 'cluster.local' diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py b/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py index 495eda12ef..a1177e756d 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py @@ -627,6 +627,7 @@ class AppOperator(object): controller_labels_set.add(constants.CONTROL_PLANE_LABEL) compute_labels_set.add(constants.COMPUTE_NODE_LABEL) compute_labels_set.add(constants.OPENVSWITCH_LABEL) + compute_labels_set.add(constants.SRIOV_LABEL) # Get controller host(s) controller_hosts =\ diff --git a/sysinv/sysinv/sysinv/sysinv/helm/neutron.py b/sysinv/sysinv/sysinv/sysinv/helm/neutron.py index 63bea9aa2b..b7c353d5e3 100644 --- a/sysinv/sysinv/sysinv/sysinv/helm/neutron.py +++ b/sysinv/sysinv/sysinv/sysinv/helm/neutron.py @@ -16,6 +16,7 @@ from sqlalchemy.orm.exc import NoResultFound LOG = logging.getLogger(__name__) DATA_NETWORK_TYPES = [constants.NETWORK_TYPE_DATA] +SRIOV_NETWORK_TYPES = [constants.NETWORK_TYPE_PCI_SRIOV] class NeutronHelm(openstack.OpenstackBaseHelm): @@ -44,12 +45,13 @@ class NeutronHelm(openstack.OpenstackBaseHelm): }, 'replicas': { 'server': self._num_controllers() - } + }, }, 'network': { 'interface': { 'tunnel': 'docker0' }, + 'backend': ['openvswitch', 'sriov'], }, 'conf': { 'neutron': self._get_neutron_config(), @@ -84,6 +86,9 @@ class NeutronHelm(openstack.OpenstackBaseHelm): 'neutron_metadata-agent': { 'hosts': self._get_per_host_overrides() }, + 'neutron_sriov-agent': { + 'hosts': self._get_per_host_overrides() + }, } }, 'labels': self._get_labels_overrides(), @@ -155,7 +160,8 @@ class NeutronHelm(openstack.OpenstackBaseHelm): 'name': hostname, 'conf': { 'plugins': { - 'openvswitch_agent': self._get_dynamic_ovs_agent_config(host) + 'openvswitch_agent': self._get_dynamic_ovs_agent_config(host), + 'sriov_agent': self._get_dynamic_sriov_agent_config(host), } } } @@ -219,6 +225,27 @@ class NeutronHelm(openstack.OpenstackBaseHelm): }, } + def _get_dynamic_sriov_agent_config(self, host): + physical_device_mappings = "" + for iface in sorted(self.dbapi.iinterface_get_by_ihost(host.id), + key=self._interface_sort_key): + if self._is_sriov_network_type(iface): + # obtain the assigned providernets for interface + providernets = self._get_interface_providernets(iface) + port_name = self._get_interface_port_name(iface) + for providernet in providernets: + physical_device_mappings += ('%s:%s,' % (providernet, port_name)) + sriov_nic = { + 'physical_device_mappings': str(physical_device_mappings), + } + + return { + 'securitygroup': { + 'firewall_driver': 'noop', + }, + 'sriov_nic': sriov_nic, + } + def _get_neutron_config(self): neutron_config = { 'DEFAULT': { @@ -284,6 +311,10 @@ class NeutronHelm(openstack.OpenstackBaseHelm): networktypelist = utils.get_network_type_list(iface) return bool(any(n in DATA_NETWORK_TYPES for n in networktypelist)) + def _is_sriov_network_type(self, iface): + networktypelist = utils.get_network_type_list(iface) + return bool(any(n in SRIOV_NETWORK_TYPES for n in networktypelist)) + def _get_interface_providernets(self, iface): """ Return the provider networks of the supplied interface as a list. @@ -293,6 +324,15 @@ class NeutronHelm(openstack.OpenstackBaseHelm): return [] return [x.strip() for x in providernetworks.split(',')] + def _get_interface_port_name(self, iface): + """ + Determine the port name of the underlying device. + """ + assert iface['iftype'] == constants.INTERFACE_TYPE_ETHERNET + port = self.dbapi.port_get_by_interface(iface.id) + if port: + return port[0]['name'] + def _get_interface_primary_address(self, context, host, iface): """ Determine the primary IP address on an interface (if any). If multiple