Fix Network Templates Verification for environments with DPDK nodes

Don't check private VLAN's when there is the only node
without DPDK.

Change-Id: I94ee39df1d571e9f25b7083a23cef4be58303562
Related-Bug: #1566963
(cherry picked from commit 87f2304684 )
This commit is contained in:
Fedor Zhadaev 2016-04-28 12:28:48 +03:00
parent 356a746c5c
commit f8a987a0b5
6 changed files with 168 additions and 11 deletions

View File

@ -81,6 +81,16 @@ class NeutronManager(NetworkManager):
props.append('bond_mode=%s' % bond.mode)
return props
@classmethod
def dpdk_enabled_for_node(cls, node):
for iface in node.nic_interfaces:
if objects.NIC.dpdk_enabled(iface):
return True
for iface in node.bond_interfaces:
if objects.Bond.dpdk_enabled(iface):
return True
return False
class NeutronManagerLegacy(AssignIPsLegacyMixin, NeutronManager):
pass
@ -190,6 +200,19 @@ class NeutronManager70(
return endpoints
@classmethod
def get_node_endpoint_by_network_role(cls, node, network_role):
"""Get endpoint name for a given role name for node"""
template = node.network_template
for role in node.all_roles:
role_templates = template['templates_for_node_role'][role]
for role_template in role_templates:
role_mapping = template['templates'][role_template]['roles']
if network_role in role_mapping:
return role_mapping[network_role]
return None
@classmethod
def get_node_network_mapping(cls, node):
"""Get (network, endpoint) mappings for node with loaded template
@ -441,6 +464,29 @@ class NeutronManager70(
}
cls._update_attrs(node_data)
@classmethod
def dpdk_enabled_for_node(cls, node):
if node.network_template:
endpoint_name = cls.get_node_endpoint_by_network_role(
node, 'neutron/private')
if not endpoint_name:
return False
template_names = set()
for role in node.all_roles:
template_names.update(
node.network_template['templates_for_node_role'][role])
templates = node.network_template['templates']
for tmpl_name in template_names:
transformations = templates[tmpl_name]['transformations']
for t in transformations:
if (t['action'] in ['add-port', 'add-bond'] and
t.get('provider') == 'dpdkovs' and
t.get('bridge') == endpoint_name):
return True
return False
else:
return super(NeutronManager70, cls).dpdk_enabled_for_node(node)
class NeutronManager80(AllocateVIPs80Mixin, NeutronManager70):
pass

View File

@ -1246,13 +1246,10 @@ class Node(NailgunObject):
@classmethod
def dpdk_enabled(cls, instance):
for iface in instance.nic_interfaces:
if NIC.dpdk_enabled(iface):
return True
for iface in instance.bond_interfaces:
if Bond.dpdk_enabled(iface):
return True
return False
network_manager = Cluster.get_network_manager(instance.cluster)
if not hasattr(network_manager, 'dpdk_enabled_for_node'):
return False
return network_manager.dpdk_enabled_for_node(instance)
@classmethod
def sriov_enabled(cls, instance):

View File

@ -965,6 +965,13 @@ class BaseNetworkVerification(object):
self.config = config
def get_ifaces_on_undeployed_node(self, node, node_json, networks_to_skip):
"""Get list of interfaces and their VLANs to be checked for the node
:param node: Node object
:param node_json: dictionary for saving result
:param networks_to_skip: list of networks, which should be skipped
:return:
"""
# Save bonds info to be able to check net-probe results w/o
# need to access nodes in DB (node can be deleted before the test is
# completed). This info is needed for non-deployed nodes only.
@ -1011,6 +1018,13 @@ class BaseNetworkVerification(object):
{'iface': iface.name, 'vlans': vlans})
def get_ifaces_on_deployed_node(self, node, node_json, networks_to_skip):
"""Get list of interfaces and their VLANs to be checked for the node
:param node: Node object
:param node_json: dictionary for saving result
:param networks_to_skip: list of networks, which should be skipped
:return:
"""
for iface in node.interfaces:
# In case of present bond interfaces - collect assigned networks
# against bonds themselves. We can check bonds as they are up on
@ -1177,6 +1191,7 @@ class VerifyNetworksForTemplateMixin(object):
transformations = template['transformations']
vlan_ids = cls._get_private_vlan_range(cluster, template)
private_endpoint = template['roles'].get('neutron/private')
for transformation in transformations:
if transformation['action'] in ['add-port', 'add-bond']:
@ -1186,7 +1201,7 @@ class VerifyNetworksForTemplateMixin(object):
if (transformation.get('provider', '') == 'dpdkovs' and
node.status == consts.NODE_STATUSES.ready and
transformation.get('bridge', '') ==
consts.DEFAULT_BRIDGES_NAMES.br_prv):
private_endpoint):
continue
yield transformation, vlan_ids
@ -1231,13 +1246,21 @@ class VerifyNetworksForTemplateMixin(object):
node_json['bonds'] = bonds
@classmethod
def get_ifaces_from_template_on_deployed_node(cls, node, node_json):
def get_ifaces_from_template_on_deployed_node(cls, node, node_json,
skip_private):
"""Retrieves list of network interfaces on the deployed node
List is retrieved from the network template.
"""
ifaces = collections.defaultdict(set)
net_manager = objects.Cluster.get_network_manager(node.cluster)
private_endpoint = \
net_manager.get_node_endpoint_by_network_role(node,
'neutron/private')
for transformation, vlan_ids in cls._get_transformations(node):
if (skip_private and transformation.get('bridge', '') ==
private_endpoint):
continue
if transformation['action'] == 'add-port':
cls._add_interface(ifaces, transformation['name'], vlan_ids)
elif transformation['action'] == 'add-bond':
@ -1270,7 +1293,9 @@ class VerifyNetworksForTemplateMixin(object):
def get_ifaces_on_deployed_node(self, node, node_json, networks_to_skip):
"""Retrieves list of network interfaces on the deployed node."""
if node.network_template:
self.get_ifaces_from_template_on_deployed_node(node, node_json)
self.get_ifaces_from_template_on_deployed_node(
node, node_json,
skip_private=consts.NETWORKS.private in networks_to_skip)
return
super(VerifyNetworksForTemplateMixin, self

View File

@ -1797,3 +1797,62 @@ class TestNeutronManager80(BaseIntegrationTest):
)
self._check_nic_mapping(node, expected_mapping)
def test_node_dpdk_enabled_w_template(self):
template = {
"templates_for_node_role": {
"cinder": [],
"controller": [],
"test_role": [
"storage",
"private"
]
},
"templates": {
"storage": {
"transformations": [
{
"action": "add-br",
"name": "br-storage"
},
{
"action": "add-port",
"bridge": "br-storage",
"name": "<% if3 %>"
}
],
"roles": {
"storage": "br-storage"
}
},
"private": {
"transformations": [
{
"action": "add-br",
"name": "br-prv",
"provider": "ovs",
"vendor_specific": {
"datapath_type": "netdev"
}
},
{
"action": "add-port",
"bridge": "br-prv",
"name": "<% if4 %>.101",
"provider": "dpdkovs"
}
],
"roles": {
"neutron/private": "br-prv"
}
},
}
}
node = mock.Mock(network_template=template,
all_roles=['test_role'])
self.assertTrue(self.net_manager.dpdk_enabled_for_node(node))
template['templates_for_node_role']['test_role'].remove('private')
self.assertFalse(self.net_manager.dpdk_enabled_for_node(node))

View File

@ -635,7 +635,8 @@ class TestNetworkVerificationWithTemplates90(BaseIntegrationTest):
{"name": "eth3", "mac": "00:00:00:00:22:99"}]
)
self.cluster = self.env.create(
release_kwargs={'version': 'liberty-9.0'},
release_kwargs={'version': 'mitaka-9.0',
'operating_system': consts.RELEASE_OS.ubuntu},
cluster_kwargs={
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
'net_segment_type': net_type,
@ -658,10 +659,25 @@ class TestNetworkVerificationWithTemplates90(BaseIntegrationTest):
}]
)
objects.Cluster.patch_attributes(
self.cluster,
{'editable': {
'common': {
'libvirt_type': {
'value': consts.HYPERVISORS.kvm}}}})
template = self.env.read_fixtures(['network_template_90'])[0]
template.pop('pk')
self.upload_template(self.cluster['id'], template)
for node in self.cluster.nodes:
objects.Node.update_attributes(
node,
{'hugepages':
{'dpdk': {'value': 128},
'nova': {'value': {'2048': 128}}}}
)
if net_type == consts.NEUTRON_SEGMENT_TYPES.vlan:
self.private_vlan_ids = list(range(1000, 1031))
else:

View File

@ -537,6 +537,13 @@ class TestCheckBeforeDeploymentTask(BaseTestCase):
def test_dpdk_hugepages_are_not_configured(self):
net_template = self.env.read_fixtures(['network_template_90'])[0]
del self.cluster.nodes[0]
self.env.create_nodes_w_interfaces_count(
1, 6,
roles=['compute'],
cluster_id=self.cluster.id
)
self.node = self.cluster.nodes[0]
objects.Cluster.set_network_template(
self.cluster,
@ -560,6 +567,13 @@ class TestCheckBeforeDeploymentTask(BaseTestCase):
def test_nova_hugepages_are_not_configured_with_dpdk_enabled(self):
net_template = self.env.read_fixtures(['network_template_90'])[0]
del self.cluster.nodes[0]
self.env.create_nodes_w_interfaces_count(
1, 6,
roles=['compute'],
cluster_id=self.cluster.id
)
self.node = self.cluster.nodes[0]
objects.Cluster.set_network_template(
self.cluster,