Add a single option to override the default hypervisor name

Currently neutron uses socket.gethostname() to determine hypervisor
names, but this implementation is not fully compatible with libvirt
driver which uses canonical name for hypervisor name.
This incompatibility causes an issue with root resource provider
detection if a deployment uses FQDNs as canonicanl names.

This change introduces the resource_provider_default_hypervisor option,
so that users can override the hypervisor name by the single option(*1)
instead of setting two list options(*2). This is especially useful if
the deployment has multiple bridges or interfaces.

(*1)
[OVS]
resource_provider_bandwidths=br-data1:1024:1024,br-data2:1024:1024,\
br-data3:1024,1024,br-data4,1024:1024
resource_provider_default_hypervisor=compute0.mydomain

(*2)
[OVS]
resource_provider_bandwidths=br-data1:1024:1024,br-data2:1024:1024,\
br-data3:1024,1024,br-data4,1024:1024
resource_provider_hypervisors=br-data1:compute0.mydomain,br-data2:\
compute0.mydomain,br-data3:compute0.mydomain,br-data4:compute0.mydomain

Related-Bug: #1926693
Change-Id: I692219200535df3af1265248e88c96947e4d8f9d
This commit is contained in:
Takashi Kajinami 2020-11-20 22:29:19 +09:00
parent 2c192b78a2
commit ddf0fef28b
7 changed files with 55 additions and 11 deletions

View File

@ -71,24 +71,27 @@ def is_agent_down(heart_beat_time):
# TODO(bence romsics): rehome this to neutron_lib.placement.utils
def default_rp_hypervisors(hypervisors, device_mappings):
def default_rp_hypervisors(hypervisors, device_mappings,
default_hypervisor=None):
"""Fill config option 'resource_provider_hypervisors' with defaults.
Default hypervisor names to socket.gethostname(). Since libvirt knows
itself by the same name, the default is good for libvirt.
Default hypervisor names to socket.gethostname() unless default_hypervisor
is set.
:param hypervisors: Config option 'resource_provider_hypervisors'
as parsed by oslo.config, that is a dict with keys of physical devices
and values of hypervisor names.
:param device_mappings: Device mappings standardized to the list-valued
format.
:param default_hypervisor: Default hypervisor hostname.
"""
default_hypervisor = socket.gethostname()
_default_hypervisor = default_hypervisor or socket.gethostname()
rv = {}
for _physnet, devices in device_mappings.items():
for device in devices:
if device in hypervisors:
rv[device] = hypervisors[device]
else:
rv[device] = default_hypervisor
rv[device] = _default_hypervisor
return rv

View File

@ -65,8 +65,13 @@ sriov_nic_opts = [
"hypervisor name is used to locate the parent of the "
"resource provider tree. Only needs to be set in the "
"rare case when the hypervisor name is different from "
"the DEFAULT.host config option value as known by the "
"nova-compute managing that hypervisor.")),
"the resource_provider_default_hypervisor config "
"option value as known by the nova-compute managing "
"that hypervisor.")),
cfg.StrOpt('resource_provider_default_hypervisor',
help=_("The default hypervisor name used to locate the parent "
"of the resource provider. If this option is not set, "
"socket.gethostname() is used")),
cfg.DictOpt('resource_provider_inventory_defaults',
default={'allocation_ratio': 1.0,
'min_unit': 1,

View File

@ -84,8 +84,13 @@ ovs_opts = [
"hypervisor name is used to locate the parent of the "
"resource provider tree. Only needs to be set in the "
"rare case when the hypervisor name is different from "
"the DEFAULT.host config option value as known by the "
"nova-compute managing that hypervisor.")),
"the resource_provider_default_hypervisor config "
"option value as known by the nova-compute managing "
"that hypervisor.")),
cfg.StrOpt('resource_provider_default_hypervisor',
help=_("The default hypervisor name used to locate the parent "
"of the resource provider. If this option is not set, "
"socket.gethostname() is used")),
cfg.DictOpt('resource_provider_inventory_defaults',
default={'allocation_ratio': 1.0,
'min_unit': 1,

View File

@ -520,7 +520,8 @@ class SriovNicAgentConfigParser(object):
cfg.CONF.SRIOV_NIC.resource_provider_inventory_defaults)
self.rp_hypervisors = utils.default_rp_hypervisors(
cfg.CONF.SRIOV_NIC.resource_provider_hypervisors,
self.device_mappings
self.device_mappings,
cfg.CONF.SRIOV_NIC.resource_provider_default_hypervisor,
)
self._validate()

View File

@ -222,7 +222,8 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
ovs_conf.resource_provider_inventory_defaults)
self.rp_hypervisors = utils.default_rp_hypervisors(
ovs_conf.resource_provider_hypervisors,
{k: [v] for k, v in self.bridge_mappings.items()}
{k: [v] for k, v in self.bridge_mappings.items()},
ovs_conf.resource_provider_default_hypervisor
)
self.setup_physical_bridges(self.bridge_mappings)

View File

@ -89,6 +89,7 @@ class TestDefaultRpHypervisors(base.BaseTestCase):
utils.default_rp_hypervisors(
hypervisors={},
device_mappings={'physnet0': ['eth0', 'eth1']},
default_hypervisor=None,
)
)
@ -97,5 +98,24 @@ class TestDefaultRpHypervisors(base.BaseTestCase):
utils.default_rp_hypervisors(
hypervisors={'eth0': 'thathost'},
device_mappings={'physnet0': ['eth0', 'eth1']},
default_hypervisor=None,
)
)
self.assertEqual(
{'eth0': 'defaulthost', 'eth1': 'defaulthost'},
utils.default_rp_hypervisors(
hypervisors={},
device_mappings={'physnet0': ['eth0', 'eth1']},
default_hypervisor='defaulthost',
)
)
self.assertEqual(
{'eth0': 'thathost', 'eth1': 'defaulthost'},
utils.default_rp_hypervisors(
hypervisors={'eth0': 'thathost'},
device_mappings={'physnet0': ['eth0', 'eth1']},
default_hypervisor='defaulthost',
)
)

View File

@ -0,0 +1,9 @@
---
fixes:
- |
The new ``resource_provider_defualt_hypervisor`` option has been added,
to replace the default hypervisor name to locates the root resource
provider without giving a complete list of interfaces or bridges in
the ``resource_provider_hypervisors`` option. This option is located in
the ``[ovs]`` ini-section for ``ovs-agent`` and ``[sriov_nic]`` ini-section
for ``sriov-agent``.