Calculation of interface types from templates fixed

In case of adding port on bond 'ether' type was set
for interface. This was root cause of the issue -
bond was processed as nic.

Closes-Bug: #1602817
Change-Id: I6a5136ce9ce5398aa6d55c795857769a7a41f7b0
This commit is contained in:
Dmitry Guryanov 2016-10-28 13:20:09 +03:00 committed by Georgy Kibardin
parent 9482abc11d
commit 392f3859ff
5 changed files with 569 additions and 30 deletions

View File

@ -34,7 +34,7 @@ from nailgun.extensions.network_manager.manager import NetworkManager
from nailgun import objects
from nailgun.extensions.network_manager.serializers.neutron_serializers \
import NeutronNetworkTemplateSerializer70
import NeutronNetworkTemplateSerializer110
class NeutronManager(NetworkManager):
@ -363,7 +363,7 @@ class NeutronManager70(
except ValueError:
vlan = None
return (iface, vlan)
return iface, vlan
@classmethod
def get_interfaces_from_template(cls, node):
@ -372,15 +372,37 @@ class NeutronManager70(
Returns a list of bare interfaces and bonds.
"""
transformations = \
NeutronNetworkTemplateSerializer70.generate_transformations(node)
NeutronNetworkTemplateSerializer110.generate_transformations(node)
interfaces = {}
for tx in transformations:
if tx['action'] == 'add-port':
key = tx.get('bridge', tx['name'])
name = tx['name']
key = tx.get('bridge', name)
iface_type = consts.NETWORK_INTERFACE_TYPES.ether
if tx.get('provider') == consts.NEUTRON_L23_PROVIDERS.ovs:
iface_name = name
vlan = tx.get('vlan_id')
else:
iface_name, vlan = cls._split_iface_name(name)
if vlan is not None:
# We can't resolve bond type in case of adding port
# on the bond. Ether type can be set only if NIC with
# iface_name present in the DB
nic = objects.NIC.get_nic_by_name(node, iface_name)
if nic is None:
# We can't detect if vlan configured on the non
# existent NIC. In this case iface will have type
# BOND. Should be fixed in
# https://bugs.launchpad.net/fuel/+bug/1664286
iface_type = consts.NETWORK_INTERFACE_TYPES.bond
interfaces[key] = {
'name': tx['name'],
'type': consts.NETWORK_INTERFACE_TYPES.ether
'name': name,
'type': iface_type
}
if tx['action'] == 'add-bond':
@ -489,8 +511,8 @@ class NeutronManager70(
if nic is None:
raise errors.NetworkTemplateCannotBeApplied(
"Networks cannot be assigned as interface with name "
"{0} does not exist for node {1}"
.format(iface, objects.Node.get_slave_name(node))
"{0} does not exist for node {1}".format(
iface, objects.Node.get_slave_name(node))
)
node_ifaces[iface]['id'] = nic.id

View File

@ -44,6 +44,8 @@ from nailgun.extensions.network_manager.managers.neutron import \
NeutronManager70
from nailgun.extensions.network_manager.managers.neutron import \
NeutronManager80
from nailgun.extensions.network_manager.managers.neutron import \
NeutronManager90
from nailgun.extensions.network_manager.managers.nova_network import \
NovaNetworkManager
from nailgun.extensions.network_manager.managers.nova_network import \
@ -1698,70 +1700,51 @@ class TestTemplateManager70(BaseIntegrationTest):
def test_get_interfaces_from_template(self):
expected_interfaces = {
'br-aux': {
'interface_properties': {},
'name': 'eth3.103',
'offloading_modes': [],
'name': 'eth2.103',
'type': 'ether'
},
'br-ex': {
'interface_properties': {},
'name': 'eth1',
'offloading_modes': [],
'type': 'ether'
},
'br-fw-admin': {
'interface_properties': {},
'name': 'eth0',
'offloading_modes': [],
'type': 'ether'
},
'br-keystone': {
'interface_properties': {},
'name': 'eth4.202',
'offloading_modes': [],
'type': 'ether'
},
'br-mgmt': {
'bond_properties': {'mode': u'active-backup'},
'name': u'lnxbond0',
'offloading_modes': [],
'slaves': [{'name': u'eth3'}, {'name': u'eth4'}],
'type': 'bond'
},
'br-mongo': {
'interface_properties': {},
'name': u'eth4.201',
'offloading_modes': [],
'type': 'ether'
},
'br-storage': {
'interface_properties': {},
'name': 'eth1.102',
'offloading_modes': [],
'type': 'ether'
},
'eth2': {
'interface_properties': {},
'name': 'eth2',
'offloading_modes': [],
'type': 'ether'
},
'eth3.101': {
'interface_properties': {},
'name': u'eth3.101',
'offloading_modes': [],
'type': 'ether'
},
'eth4.101': {
'interface_properties': {},
'name': u'eth4.101',
'offloading_modes': [],
'type': 'ether'
}
}
interfaces = self.nm.get_interfaces_from_template(self.env.nodes[0])
self.assertItemsEqual(interfaces, expected_interfaces)
self.assertEqual(expected_interfaces, interfaces)
def test_reassign_networks_based_on_template(self):
expected_mapping = {
@ -1947,3 +1930,59 @@ class TestNeutronManager80(BaseIntegrationTest):
template['templates_for_node_role']['test_role'].remove('private')
self.assertFalse(self.net_manager.dpdk_enabled_for_node(node))
class TestTemplateManager90(BaseIntegrationTest):
def setUp(self):
super(TestTemplateManager90, self).setUp()
self.cluster = self.env.create(
release_kwargs={'version': '1111-9.0'},
cluster_kwargs={
'api': True,
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
}
)
self.cluster = objects.Cluster.get_by_uid(self.cluster['id'])
self.nm = objects.Cluster.get_network_manager(self.cluster)
self.net_templates = self.env.read_fixtures(['network_template_90'])
def test_get_network_manager(self):
self.assertIs(self.nm, NeutronManager90)
def test_get_interfaces_from_template(self):
nodes = self.env.create_nodes_w_interfaces_count(
1,
if_count=15,
cluster_id=self.cluster.id,
status=consts.NODE_STATUSES.ready,
roles=["controller"],
iface_name_prefix='eno{0}'
)
objects.Cluster.set_network_template(
self.cluster,
self.net_templates[3]
)
interfaces = self.nm.get_interfaces_from_template(nodes[0])
expected_interfaces = {
'br-fw-admin': {'type': 'ether', 'name': 'eno3'},
'bond0': {
'bond_properties': {
'lacp_rate': 'fast',
'mode': '802.3ad',
'xmit_hash_policy': 'layer3+4'
},
'type': 'bond',
'name': 'bond0',
'slaves': [{'name': 'eno1'}, {'name': 'eno2'}]},
'br-prv': {'type': 'bond', 'name': 'bond0.342'},
'br-storage': {'type': 'bond', 'name': 'bond0.344'},
'br-mgmt': {'type': 'bond', 'name': 'bond0.346'},
'br-ex': {'type': 'bond', 'name': 'bond0.345'},
'br0': {'type': 'bond', 'name': 'port-with-tag-111'},
'br1': {'type': 'bond', 'name': 'eno3333.222'},
'br2': {'type': 'ether', 'name': 'eno3333'}
}
self.assertEqual(expected_interfaces, interfaces)

View File

@ -58,6 +58,42 @@ class TestHandlers(BaseIntegrationTest):
self.assertEqual(200, resp.status_code)
self.assertEqual(template, resp.json_body)
def test_network_template_add_node(self):
cluster = self.env.create(
release_kwargs={'version': '1111-9.0'},
cluster_kwargs={
'api': False,
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron
}
)
self.env.create_nodes_w_interfaces_count(
5,
if_count=15,
cluster_id=cluster.id,
status=consts.NODE_STATUSES.ready,
roles=["controller"],
iface_name_prefix='eno{0}'
)
template = self.env.read_fixtures(['network_template_90'])[3]
template.pop('pk') # PK is not needed
resp = self.app.put(
reverse(
'TemplateNetworkConfigurationHandler',
kwargs={'cluster_id': cluster.id},
),
jsonutils.dumps(template),
headers=self.default_headers
)
self.assertEqual(200, resp.status_code)
self.assertEquals(template, resp.json_body)
resp = self.get_template(cluster.id)
self.assertEqual(200, resp.status_code)
self.assertEqual(template, resp.json_body)
def test_network_template_upload_on_multi_group_cluster(self):
cluster = self.env.create_cluster(
api=False,
@ -174,3 +210,38 @@ class TestHandlers(BaseIntegrationTest):
# error (403 in this case)
db().commit()
self.check_put_delete_template(cluster, status not in allowed)
def test_network_template_upload_90(self):
cluster = self.env.create(
release_kwargs={'version': '1111-9.0'},
cluster_kwargs={
'api': True,
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
}
)
self.env.create_nodes_w_interfaces_count(
1,
if_count=15,
cluster_id=cluster.id,
status=consts.NODE_STATUSES.ready,
roles=["controller"],
iface_name_prefix='eno{0}'
)
template = self.env.read_fixtures(['network_template_90'])[3]
template.pop('pk') # PK is not needed
resp = self.app.put(
reverse(
'TemplateNetworkConfigurationHandler',
kwargs={'cluster_id': cluster.id},
),
jsonutils.dumps(template),
headers=self.default_headers
)
self.assertEqual(200, resp.status_code)
self.assertEquals(template, resp.json_body)
resp = self.get_template(cluster.id)
self.assertEqual(200, resp.status_code)
self.assertEqual(template, resp.json_body)

View File

@ -891,4 +891,410 @@
}
}
}
},
{
"pk": 4,
"adv_net_template": {
"default": {
"network_assignments": {
"management": {
"ep": "br-mgmt"
},
"ceph_cluster": {
"ep": "br-cluster"
},
"storage": {
"ep": "br-storage"
},
"public": {
"ep": "br-ex"
},
"private": {
"ep": "br-prv"
},
"fuelweb_admin": {
"ep": "br-fw-admin"
}
},
"templates_for_node_role": {
"ceph-osd": [
"common",
"storage",
"ceph_cluster"
],
"compute": [
"common",
"public",
"private",
"storage"
],
"mongo": [
"common"
],
"kafka": [
"common",
"public"
],
"elasticsearch_kibana": [
"common",
"public",
"private",
"storage"
],
"base-os": [
"common"
],
"controller": [
"common",
"public",
"private",
"storage"
],
"influxdb_grafana": [
"common",
"public",
"private",
"storage"
],
"infrastructure_alerting": [
"common",
"public",
"private",
"storage"
],
"ceph-mon": [
"common",
"storage",
"ceph_cluster"
],
"standalone-rabbitmq": [
"common",
"public"
]
},
"network_scheme": {
"ceph_cluster": {
"endpoints": [
"br-cluster"
],
"transformations": [
{
"action": "add-br",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "br-cluster",
"mtu": 9000
},
{
"action": "add-port",
"bridge": "br-cluster",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "bond0.343",
"mtu": 9000
}
],
"roles": {
"ceph/replication": "br-cluster"
}
},
"storage": {
"endpoints": [
"br-storage"
],
"transformations": [
{
"action": "add-br",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "br-storage",
"mtu": 9000
},
{
"action": "add-port",
"bridge": "br-storage",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "bond0.344",
"mtu": 9000
}
],
"roles": {
"ceph/radosgw": "br-storage",
"rados_gw_plublic_vip": "br-storage",
"storage": "br-storage",
"cinder/iscsi": "br-storage",
"ceph/public": "br-storage"
}
},
"public": {
"endpoints": [
"br-ex"
],
"transformations": [
{
"action": "add-br",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "br-ex",
"mtu": 9000
},
{
"action": "add-br",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"mtu": 9000,
"name": "br-floating",
"provider": "ovs"
},
{
"action": "add-patch",
"bridges": [
"br-floating",
"br-ex"
],
"mtu": 9000,
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"provider": "ovs"
},
{
"action": "add-port",
"bridge": "br-ex",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "bond0.345",
"mtu": 9000
}
],
"roles": {
"ex": "br-ex",
"neutron/floating": "br-floating",
"public/vip": "br-ex"
}
},
"private": {
"endpoints": [
"br-prv"
],
"transformations": [
{
"action": "add-br",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "br-prv",
"mtu": 9000
},
{
"action": "add-port",
"bridge": "br-prv",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "bond0.342",
"mtu": 9000
}
],
"roles": {
"neutron/private": "None",
"neutron/mesh": "br-prv"
}
},
"common": {
"endpoints": [
"br-fw-admin",
"br-mgmt"
],
"transformations": [
{
"action": "add-br",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "br-fw-admin",
"mtu": 9000
},
{
"action": "add-br",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "br-mgmt",
"mtu": 9000
},
{
"action": "add-port",
"bridge": "br-fw-admin",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "<%if2%>",
"mtu": 9000
},
{
"action": "add-port",
"bridge": "br1",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "<%if3%>.222",
"mtu": 9000
},
{
"action": "add-port",
"bridge": "br2",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "<%if3%>",
"mtu": 9000
},
{
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"bond_properties": {
"lacp_rate": "fast",
"mode": "802.3ad",
"xmit_hash_policy": "layer3+4"
},
"name": "bond0",
"interface_properties": {
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"mtu": 9000
},
"action": "add-bond",
"interfaces": [
"<%if0%>",
"<%if1%>"
],
"mtu": 9000
},
{
"action": "add-port",
"bridge": "br-mgmt",
"ethtool": {
"offload": {
"large-receive-offload": false,
"generic-receive-offload": false
}
},
"name": "bond0.346",
"mtu": 9000
},
{
"action": "add-port",
"name": "port-with-tag-111",
"bridge": "br0",
"vlan_id": 111,
"provider": "ovs"
}
],
"roles": {
"keystone/api": "br-mgmt",
"neutron/api": "br-mgmt",
"mgmt/database": "br-mgmt",
"sahara/api": "br-mgmt",
"admin/pxe": "br-fw-admin",
"kibana": "br-mgmt",
"mgmt/corosync": "br-mgmt",
"mongo/db": "br-mgmt",
"ceilometer/api": "br-mgmt",
"glance/api": "br-mgmt",
"nova/migration": "br-mgmt",
"rados_gw_management_vip": "br-mgmt",
"mgmt/vip": "br-mgmt",
"fw-admin": "br-fw-admin",
"mgmt/messaging": "br-mgmt",
"management": "br-mgmt",
"swift/api": "br-mgmt",
"heat/api": "br-mgmt",
"mgmt/memcache": "br-mgmt",
"mgmt/api": "br-mgmt",
"murano/api": "br-mgmt",
"infrastructure_alerting_ui": "br-mgmt",
"grafana": "br-mgmt",
"influxdb_vip": "br-mgmt",
"nova/api": "br-mgmt",
"elasticsearch": "br-mgmt",
"horizon": "br-mgmt",
"infrastructure_alerting": "br-mgmt",
"cinder/api": "br-mgmt",
"swift/replication": "br-mgmt"
}
}
},
"nic_mapping": {
"default": {
"if0": "eno1",
"if1": "eno2",
"if2": "eno3",
"if3": "eno3333"
}
}
}
}
}]

View File

@ -457,11 +457,12 @@ class EnvironmentManager(object):
Default random MAC is generated for each interface
"""
nodes = []
prefix_tpl = kwargs.get('iface_name_prefix', 'eth{0}')
for i in range(nodes_count):
meta = self.default_metadata()
if_list = [
{
"name": "eth{0}".format(i),
"name": prefix_tpl.format(i),
"mac": self.generate_random_mac(),
}
for i in range(if_count)]