Support pci-pt and sr-iov on the same interface

This update allows both pci-passthrough and pci-sriov network types to
be assigned to an interface.

Change-Id: I1e11e02293ada434372bec3689dee1d395877504
This commit is contained in:
Teresa Ho 2018-05-17 09:48:16 -04:00 committed by Jack Ding
parent 6ea3f51de6
commit 3c8f8860b4
5 changed files with 42 additions and 9 deletions

View File

@ -460,8 +460,9 @@ class InterfaceController(rest.RestController):
elif '/sriov_numvfs' in p['path']:
temp_interface['sriov_numvfs'] = p['value']
# If network type is not pci-sriov, reset the sriov-numvfs to zero
if temp_interface['sriov_numvfs'] is not None and \
temp_interface['networktype'] != constants.NETWORK_TYPE_PCI_SRIOV:
if (temp_interface['sriov_numvfs'] is not None and
temp_interface['networktype'] is not None and
constants.NETWORK_TYPE_PCI_SRIOV not in temp_interface['networktype']):
temp_interface['sriov_numvfs'] = None
_check_interface_sriov(temp_interface.as_dict(), ihost)
@ -810,7 +811,9 @@ def _check_interface_sriov(interface, ihost, from_profile=False):
if 'networktype' in interface.keys() and interface['networktype'] == constants.NETWORK_TYPE_NONE:
return interface
if ('networktype' in interface.keys() and interface['networktype'] == constants.NETWORK_TYPE_PCI_SRIOV and
networktypelist = cutils.get_network_type_list(interface)
if ('networktype' in interface.keys() and
constants.NETWORK_TYPE_PCI_SRIOV in networktypelist and
'sriov_numvfs' not in interface.keys()):
raise wsme.exc.ClientSideError(_("A network type of pci-sriov must specify "
@ -819,12 +822,13 @@ def _check_interface_sriov(interface, ihost, from_profile=False):
if ('sriov_numvfs' in interface.keys() and interface['sriov_numvfs']
is not None and int(interface['sriov_numvfs']) > 0 and
('networktype' not in interface.keys() or
interface['networktype'] != constants.NETWORK_TYPE_PCI_SRIOV)):
constants.NETWORK_TYPE_PCI_SRIOV not in interface['networktype'])):
raise wsme.exc.ClientSideError(_("Number of SR-IOV VFs is specified but network "
"type is not pci-sriov."))
if ('networktype' in interface.keys() and interface['networktype'] == constants.NETWORK_TYPE_PCI_SRIOV and
if ('networktype' in interface.keys() and
constants.NETWORK_TYPE_PCI_SRIOV in networktypelist and
'sriov_numvfs' in interface.keys()):
if interface['sriov_numvfs'] is None:
@ -893,8 +897,10 @@ def _check_network_type_validity(networktypelist):
def _check_network_type_count(networktypelist):
if networktypelist and len(networktypelist) != 1:
msg = _("Network type list may only contain at most one type")
if (networktypelist and len(networktypelist) != 1 and
not cutils.is_pci_network_types(networktypelist)):
msg = _("Network type list may only contain at most one type, "
"except for PCI network types.")
raise wsme.exc.ClientSideError(msg)
@ -966,7 +972,12 @@ def _check_network_type_transition(interface, existing_interface):
networktype = cutils.get_primary_network_type(interface)
existing_networktype = cutils.get_primary_network_type(existing_interface)
if networktype == existing_networktype:
return
if networktype == constants.NETWORK_TYPE_PCI_SRIOV:
if (len(cutils.get_network_type_list(interface)) ==
len(cutils.get_network_type_list(existing_interface))):
return
else:
return
if networktype and existing_networktype:
msg = _("The network type of an interface cannot be changed without "
"first being reset back to '%s'." %

View File

@ -533,6 +533,9 @@ NETWORK_TYPE_PCI_PASSTHROUGH = 'pci-passthrough'
NETWORK_TYPE_PCI_SRIOV = 'pci-sriov'
NETWORK_TYPE_PXEBOOT = 'pxeboot'
PCI_NETWORK_TYPES = [NETWORK_TYPE_PCI_PASSTHROUGH,
NETWORK_TYPE_PCI_SRIOV]
INTERFACE_TYPE_ETHERNET = 'ethernet'
INTERFACE_TYPE_VLAN = 'vlan'
INTERFACE_TYPE_AE = 'ae'

13
sysinv/sysinv/sysinv/sysinv/common/utils.py Executable file → Normal file
View File

@ -1035,6 +1035,15 @@ def get_network_type_list(interface):
return []
def is_pci_network_types(networktypelist):
"""
Check if the network type consists of the combined PCI passthrough
and SRIOV network types.
"""
return (len(constants.PCI_NETWORK_TYPES) == len(networktypelist) and
all(i in networktypelist for i in constants.PCI_NETWORK_TYPES))
def get_primary_network_type(interface):
"""
An interface can be associated with up to 2 network types but it can only
@ -1051,6 +1060,10 @@ def get_primary_network_type(interface):
networktypes = get_network_type_list(interface)
if len(networktypes) > 1:
networktypes = [n for n in networktypes if n != constants.NETWORK_TYPE_DATA]
# If the network type is the combined PCI passthrough and SRIOV then
# return pci-sriov as the primary network type
if is_pci_network_types(networktypes):
return constants.NETWORK_TYPE_PCI_SRIOV
if len(networktypes) > 1:
raise exception.CannotDeterminePrimaryNetworkType(
iface=interface['uuid'], types=interface['networktype'])

View File

@ -574,7 +574,9 @@ class NovaPuppet(openstack.OpenstackBasePuppet):
devices = []
for iface in self.context['interfaces'].values():
network_type = utils.get_primary_network_type(iface)
if network_type == constants.NETWORK_TYPE_PCI_PASSTHROUGH:
networktypes = utils.get_network_type_list(iface)
if (network_type == constants.NETWORK_TYPE_PCI_PASSTHROUGH or
utils.is_pci_network_types(networktypes)):
port = interface.get_interface_port(self.context, iface)
device = {
'address': port['pciaddr'],

View File

@ -714,6 +714,10 @@ class InterfaceCpeEthernet(InterfaceTestCase):
'group0-data1')
self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH,
'group0-ext0')
self._create_ethernet('ptsriov',
constants.NETWORK_TYPE_PCI_PASSTHROUGH + ',' +
constants.NETWORK_TYPE_PCI_SRIOV,
'group0-ext0')
port, iface = (
self._create_ethernet('slow', constants.NETWORK_TYPE_DATA,
'group0-ext1'))