Merge "network: Always retrieve network information if available"
This commit is contained in:
commit
f2b96588ef
|
@ -280,6 +280,9 @@ class NetworkAPI(base.Base):
|
|||
:param pci_requests: The list of PCI requests to which additional PCI
|
||||
requests created here will be added.
|
||||
:type pci_requests: nova.objects.InstancePCIRequests
|
||||
|
||||
:returns: An instance of ``objects.NetworkMetadata`` for use by the
|
||||
scheduler or None.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
|
|
@ -1618,26 +1618,43 @@ class API(base_api.NetworkAPI):
|
|||
pci_requests=None):
|
||||
"""Retrieve all information for the networks passed at the time of
|
||||
creating the server.
|
||||
|
||||
:param context: The request context.
|
||||
:param requested_networks: The networks requested for the server.
|
||||
:type requested_networks: nova.objects.RequestedNetworkList
|
||||
:param pci_requests: The list of PCI requests to which additional PCI
|
||||
requests created here will be added.
|
||||
:type pci_requests: nova.objects.InstancePCIRequests
|
||||
|
||||
:returns: An instance of ``objects.NetworkMetadata`` for use by the
|
||||
scheduler or None.
|
||||
"""
|
||||
if not requested_networks or requested_networks.no_allocate:
|
||||
return
|
||||
return None
|
||||
|
||||
physnets = set()
|
||||
tunneled = False
|
||||
|
||||
neutron = get_client(context, admin=True)
|
||||
for request_net in requested_networks:
|
||||
physnet = None
|
||||
trusted = None
|
||||
vnic_type = network_model.VNIC_TYPE_NORMAL
|
||||
pci_request_id = None
|
||||
|
||||
if request_net.port_id:
|
||||
vnic_type, trusted, network_id = self._get_port_vnic_info(
|
||||
context, neutron, request_net.port_id)
|
||||
physnet = self._get_physnet_info(
|
||||
context, neutron, network_id)
|
||||
LOG.debug("Creating PCI device request for port_id=%s, "
|
||||
"vnic_type=%s, phynet_name=%s, trusted=%s",
|
||||
request_net.port_id, vnic_type, physnet,
|
||||
trusted)
|
||||
pci_request_id = None
|
||||
elif request_net.network_id and not request_net.auto_allocate:
|
||||
network_id = request_net.network_id
|
||||
physnet = self._get_physnet_info(
|
||||
context, neutron, network_id)
|
||||
|
||||
if physnet:
|
||||
physnets.add(physnet)
|
||||
|
||||
if vnic_type in network_model.VNIC_TYPES_SRIOV:
|
||||
# TODO(moshele): To differentiate between the SR-IOV legacy
|
||||
# and SR-IOV ovs hardware offload we will leverage the nic
|
||||
|
@ -1665,6 +1682,8 @@ class API(base_api.NetworkAPI):
|
|||
# Add pci_request_id into the requested network
|
||||
request_net.pci_request_id = pci_request_id
|
||||
|
||||
return objects.NetworkMetadata(physnets=physnets, tunneled=tunneled)
|
||||
|
||||
def _can_auto_allocate_network(self, context, neutron):
|
||||
"""Helper method to determine if we can auto-allocate networks
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ def register_all():
|
|||
__import__('nova.objects.migration_context')
|
||||
__import__('nova.objects.monitor_metric')
|
||||
__import__('nova.objects.network')
|
||||
__import__('nova.objects.network_metadata')
|
||||
__import__('nova.objects.network_request')
|
||||
__import__('nova.objects.numa')
|
||||
__import__('nova.objects.pci_device')
|
||||
|
|
|
@ -77,6 +77,7 @@ PCIAddressField = fields.PCIAddressField
|
|||
Enum = fields.Enum
|
||||
Field = fields.Field
|
||||
FieldType = fields.FieldType
|
||||
String = fields.String
|
||||
Set = fields.Set
|
||||
Dict = fields.Dict
|
||||
List = fields.List
|
||||
|
@ -89,6 +90,10 @@ IPV4Network = fields.IPV4Network
|
|||
IPV6Network = fields.IPV6Network
|
||||
|
||||
|
||||
class SetOfStringsField(AutoTypedField):
|
||||
AUTO_TYPE = Set(String())
|
||||
|
||||
|
||||
class BaseNovaEnum(Enum):
|
||||
def __init__(self, **kwargs):
|
||||
super(BaseNovaEnum, self).__init__(valid_values=self.__class__.ALL)
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
# Copyright 2018 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from nova.objects import base
|
||||
from nova.objects import fields
|
||||
|
||||
|
||||
@base.NovaObjectRegistry.register
|
||||
class NetworkMetadata(base.NovaObject):
|
||||
"""Hold aggregate metadata for a collection on networks.
|
||||
|
||||
This object holds aggregate information for a collection of neutron
|
||||
networks. There are two types of network collections we care about and use
|
||||
this for: the collection of networks configured or requested for a guest
|
||||
and the collection of networks available to a host. We want this
|
||||
information to allow us to map a given neutron network to the logical NICs
|
||||
it does or will use (or, rather, to identify the NUMA affinity of those
|
||||
NICs and therefore the networks). Given that there are potentially tens of
|
||||
thousands of neutron networks accessible from a given host and tens or
|
||||
hundreds of networks configured for an instance, we need a way to group
|
||||
networks by some common attribute that would identify the logical NIC it
|
||||
would use. For L2 networks, this is the physnet attribute (e.g.
|
||||
``provider:physical_network=provider1``), which is an arbitrary string used
|
||||
to distinguish between multiple physical (in the sense of physical wiring)
|
||||
networks. For L3 (tunneled) networks, this is merely the fact that they are
|
||||
L3 networks (e.g. ``provider:network_type=vxlan``) because, in neutron,
|
||||
*all* L3 networks must use the same logical NIC.
|
||||
"""
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'physnets': fields.SetOfStringsField(),
|
||||
'tunneled': fields.BooleanField(),
|
||||
}
|
|
@ -4949,18 +4949,42 @@ class TestNeutronv2WithMock(_TestNeutronv2Common):
|
|||
self.assertTrue(mock_log.called)
|
||||
|
||||
@mock.patch.object(neutronapi, 'get_client')
|
||||
def test_create_resource_requests_no_allocate(self, getclient):
|
||||
"""Tests that create_resource_requests is a noop if
|
||||
networks are specifically requested to not be allocated.
|
||||
def test_create_resource_requests_no_allocate(self, mock_get_client):
|
||||
"""Ensure physnet info is not retrieved when networks are not to be
|
||||
allocated.
|
||||
"""
|
||||
requested_networks = objects.NetworkRequestList(objects=[
|
||||
objects.NetworkRequest(network_id=net_req_obj.NETWORK_ID_NONE)
|
||||
])
|
||||
pci_requests = objects.InstancePCIRequests()
|
||||
api = neutronapi.API()
|
||||
api.create_resource_requests(
|
||||
|
||||
network_metadata = api.create_resource_requests(
|
||||
self.context, requested_networks, pci_requests)
|
||||
self.assertFalse(getclient.called)
|
||||
|
||||
self.assertFalse(mock_get_client.called)
|
||||
self.assertIsNone(network_metadata)
|
||||
|
||||
@mock.patch.object(neutronapi.API, '_get_physnet_info')
|
||||
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
||||
def test_create_resource_requests_auto_allocated(self, mock_get_client,
|
||||
mock_get_physnet_info):
|
||||
"""Ensure physnet info is not retrieved for auto-allocated networks.
|
||||
|
||||
This isn't possible so we shouldn't attempt to do it.
|
||||
"""
|
||||
requested_networks = objects.NetworkRequestList(objects=[
|
||||
objects.NetworkRequest(network_id=net_req_obj.NETWORK_ID_AUTO)
|
||||
])
|
||||
pci_requests = objects.InstancePCIRequests()
|
||||
api = neutronapi.API()
|
||||
|
||||
network_metadata = api.create_resource_requests(
|
||||
self.context, requested_networks, pci_requests)
|
||||
|
||||
mock_get_physnet_info.assert_not_called()
|
||||
self.assertEqual(set(), network_metadata.physnets)
|
||||
self.assertFalse(network_metadata.tunneled)
|
||||
|
||||
@mock.patch.object(neutronapi.API, '_get_physnet_info')
|
||||
@mock.patch.object(neutronapi.API, "_get_port_vnic_info")
|
||||
|
@ -4977,6 +5001,8 @@ class TestNeutronv2WithMock(_TestNeutronv2Common):
|
|||
objects.NetworkRequest(port_id=uuids.portid_5),
|
||||
objects.NetworkRequest(port_id=uuids.trusted_port)])
|
||||
pci_requests = objects.InstancePCIRequests(requests=[])
|
||||
# _get_port_vnic_info should be called for every NetworkRequest with a
|
||||
# port_id attribute (so six times)
|
||||
mock_get_port_vnic_info.side_effect = [
|
||||
(model.VNIC_TYPE_DIRECT, None, 'netN'),
|
||||
(model.VNIC_TYPE_NORMAL, None, 'netN'),
|
||||
|
@ -4985,12 +5011,15 @@ class TestNeutronv2WithMock(_TestNeutronv2Common):
|
|||
(model.VNIC_TYPE_DIRECT_PHYSICAL, None, 'netN'),
|
||||
(model.VNIC_TYPE_DIRECT, True, 'netN'),
|
||||
]
|
||||
# _get_physnet_info should be called for every NetworkRequest (so seven
|
||||
# times)
|
||||
mock_get_physnet_info.side_effect = [
|
||||
'physnet1', '', 'physnet1', 'physnet2', 'physnet3', 'physnet4',
|
||||
'physnet1', 'physnet1', '', 'physnet1', 'physnet2', 'physnet3',
|
||||
'physnet4',
|
||||
]
|
||||
api = neutronapi.API()
|
||||
|
||||
api.create_resource_requests(
|
||||
network_metadata = api.create_resource_requests(
|
||||
self.context, requested_networks, pci_requests)
|
||||
|
||||
self.assertEqual(5, len(pci_requests.requests))
|
||||
|
@ -5010,6 +5039,13 @@ class TestNeutronv2WithMock(_TestNeutronv2Common):
|
|||
else:
|
||||
self.assertNotIn(pci_request.PCI_TRUSTED_TAG, spec)
|
||||
|
||||
self.assertItemsEqual(
|
||||
['physnet1', 'physnet2', 'physnet3', 'physnet4'],
|
||||
network_metadata.physnets)
|
||||
# TODO(stephenfin): Expand this to be a positive check when we start
|
||||
# retrieving this information
|
||||
self.assertFalse(network_metadata.tunneled)
|
||||
|
||||
@mock.patch.object(neutronapi, 'get_client')
|
||||
def test_associate_floating_ip_conflict(self, mock_get_client):
|
||||
"""Tests that if Neutron raises a Conflict we handle it and re-raise
|
||||
|
|
|
@ -1131,6 +1131,7 @@ object_data = {
|
|||
'Network': '1.2-a977ab383aa462a479b2fae8211a5dde',
|
||||
'NetworkInterfaceMetadata': '1.2-6f3d480b40fe339067b1c0dd4d656716',
|
||||
'NetworkList': '1.2-69eca910d8fa035dfecd8ba10877ee59',
|
||||
'NetworkMetadata': '1.0-2cb8d21b34f87b0261d3e1d1ae5cf218',
|
||||
'NetworkRequest': '1.2-af1ff2d986999fbb79377712794d82aa',
|
||||
'NetworkRequestList': '1.1-15ecf022a68ddbb8c2a6739cfc9f8f5e',
|
||||
'PciDevice': '1.6-2a2612baaa1786679e52084e82ca7e66',
|
||||
|
|
Loading…
Reference in New Issue