Added driver and bus_info interface parameters

Adding driver and bus info interface parameters support with
these changes:
  1. Adding driver and bus_info parameters into nailgun DB
     and nailgun agent.
  2. Adding driver and bus_info parameters into UI dialogs
     and publishing it to astute yaml.
  3. Publishing user physical interfaces and vlan mappings
     to astute yaml.

Partially implements: blueprint support-infiniband-network

Change-Id: I4e91447a99a7ada35a2af4507725e2705aaa69d6
This commit is contained in:
Aviram Bar-Haim 2014-12-15 19:29:12 +02:00
parent 058d1adef4
commit 88f13fe99a
10 changed files with 244 additions and 23 deletions

View File

@ -211,6 +211,8 @@ class NodeAgent
int_meta[:mac] = addr
begin
int_info = Rethtool::InterfaceSettings.new(int)
int_meta[:driver] = int_info.driver
int_meta[:bus_info] = int_info.bus_info
int_meta[:max_speed] = int_info.best_mode.speed
if int_info.current_mode.speed == :unknown
int_meta[:current_speed] = nil

View File

@ -43,6 +43,8 @@ single_schema = {
"mac": base_types.MAC_ADDRESS,
"state": {"type": "string"},
"name": {"type": "string"},
"driver": {"type": "string"},
"bus_info": {"type": "string"},
}
}
},

View File

@ -134,6 +134,12 @@ def upgrade_schema():
op.add_column(
'clusters',
sa.Column('deployment_tasks', fields.JSON(), nullable=True))
op.add_column(
'node_nic_interfaces',
sa.Column('driver', sa.Text(), nullable=True))
op.add_column(
'node_nic_interfaces',
sa.Column('bus_info', sa.Text(), nullable=True))
op.add_column(
'releases',
sa.Column('deployment_tasks', fields.JSON(), nullable=True))
@ -338,6 +344,8 @@ def downgrade_schema():
op.drop_table('vmware_attributes')
op.drop_column('releases', 'vmware_attributes_metadata')
op.drop_column('clusters', 'deployment_tasks')
op.drop_column('node_nic_interfaces', 'driver')
op.drop_column('node_nic_interfaces', 'bus_info')
op.drop_column('releases', 'deployment_tasks')
op.drop_constraint('node_roles_node_fkey', 'node_roles')
op.create_foreign_key(

View File

@ -331,6 +331,8 @@ class NodeNICInterface(Base):
interface_properties = Column(JSON, default={}, nullable=False,
server_default='{}')
parent_id = Column(Integer, ForeignKey('node_bond_interfaces.id'))
driver = Column(Text)
bus_info = Column(Text)
@property
def type(self):

View File

@ -118,14 +118,18 @@
"mac": "00:25:90:6a:b1:10",
"max_speed": 1000,
"name": "eth0",
"current_speed": 1000
"current_speed": 1000,
"driver": "igb",
"bus_info": "0000:01:00.0"
},
{
"mac": "00:25:90:6a:b1:11",
"max_speed": 1000,
"name": "eth1",
"current_speed": null,
"ip": "10.20.0.3"
"ip": "10.20.0.3",
"driver": "igb",
"bus_info": "0000:02:00.0"
}
],
"disks": [
@ -307,6 +311,8 @@
"ip": "10.20.0.4",
"mac": "58:91:cF:2a:c4:1b",
"netmask": "255.255.255.0",
"driver": "igb",
"bus_info": "0000:03:00.0",
"current_speed": null,
"name": "wlan0"
},
@ -315,13 +321,17 @@
"mac": "24:b6:fd:53:63:00",
"max_speed": 100,
"name": "eth0",
"driver": "igb",
"bus_info": "0000:04:00.0",
"current_speed": 10
},
{
"mac": "54:78:ea:05:17:ba",
"max_speed": 100,
"max_speed": 56000,
"name": "eth1",
"current_speed": 20
"current_speed": 40000,
"driver": "eth_ipoib",
"bus_info": "0000:05:00.0"
}
],
"disks": [
@ -435,6 +445,8 @@
"ip": "172.18.67.167",
"netmask": "255.255.255.240",
"mac": "00:25:90:67:9f:b7",
"driver": "igb",
"bus_info": "0000:06:00.0",
"max_speed": 1000,
"current_speed": 1000
},
@ -443,6 +455,8 @@
"ip": "172.18.167.167",
"netmask": "255.255.255.240",
"mac": "00:25:90:67:9f:b8",
"driver": "igb",
"bus_info": "0000:07:00.0",
"max_speed": 1000,
"current_speed": 1000
},
@ -451,15 +465,19 @@
"ip": "172.18.167.167",
"netmask": "255.255.255.240",
"mac": "00:25:90:67:9f:b9",
"max_speed": 1000,
"current_speed": 1000
"driver": "eth_ipoib",
"bus_info": "0000:08:00.0",
"max_speed": 56000,
"current_speed": 56000
},
{
"ip": "10.20.0.5",
"mac": "00:25:90:67:9f:b6",
"max_speed": 1000,
"name": "eth0",
"current_speed": null
"current_speed": null,
"driver": "igb",
"bus_info": "0000:09:00.0"
}
],
"disks": [
@ -574,12 +592,16 @@
"mac": "00:25:90:67:9d:25",
"max_speed": 1000,
"name": "eth1",
"current_speed": null
"current_speed": null,
"driver": "mlx4_en",
"bus_info": "0000:10:00.0"
},
{
"name": "eth0",
"ip": "10.20.0.6",
"netmask": "255.255.255.240",
"driver": "igb",
"bus_info": "0000:11:00.0",
"mac": "00:25:90:67:9d:24",
"max_speed": 1000,
"current_speed": 1000
@ -699,12 +721,16 @@
"max_speed": 1000,
"name": "eth1",
"current_speed": null,
"ip": "10.20.0.7"
"ip": "10.20.0.7",
"driver": "igb",
"bus_info": "0000:12:00.0"
},
{
"name": "eth0",
"netmask": "255.255.255.224",
"mac": "00:25:90:67:9c:9c",
"driver": "igb",
"bus_info": "0000:13:00.0",
"max_speed": 1000,
"current_speed": 1000
}
@ -797,6 +823,8 @@
"ip": "10.20.0.63",
"netmask": "255.255.255.0",
"mac": "08:00:27:22:ab:aa",
"driver": "e1000",
"bus_info": "0000:14:00.0",
"max_speed": 100,
"current_speed": 100
},
@ -804,19 +832,25 @@
"name": "eth1",
"mac": "08:00:27:22:ab:ab",
"max_speed": 1000,
"current_speed": 100
"current_speed": 100,
"driver": "e1000",
"bus_info": "0000:15:00.0"
},
{
"name": "eth2",
"mac": "08:00:27:22:ab:ac",
"max_speed": 100,
"current_speed": null
"current_speed": null,
"driver": "e1000",
"bus_info": "0000:16:00.0"
},
{
"name": "eth3",
"mac": "08:00:27:22:ab:ad",
"max_speed": 100,
"current_speed": null
"current_speed": null,
"driver": "e1000",
"bus_info": "0000:17:00.0"
}
],
"disks": [
@ -881,37 +915,49 @@
"netmask": "255.255.255.0",
"mac": "52:54:00:0e:b8:f5",
"max_speed": 100,
"current_speed": 100
"current_speed": 100,
"driver": "igb",
"bus_info": "0000:18:00.0"
},
{
"name": "eth1",
"mac": "52:54:00:0e:b8:f6",
"max_speed": 1000,
"current_speed": 1000
"current_speed": 1000,
"driver": "igb",
"bus_info": "0000:19:00.0"
},
{
"name": "eth2",
"mac": "52:54:00:0e:b8:f7",
"max_speed": 100,
"current_speed": null
"current_speed": null,
"driver": "igb",
"bus_info": "0000:20:00.0"
},
{
"name": "eth3",
"mac": "52:54:00:0e:b8:f8",
"max_speed": 1000,
"current_speed": 100
"current_speed": 100,
"driver": "igb",
"bus_info": "0000:21:00.0"
},
{
"name": "eth4",
"mac": "52:54:00:0e:b8:f9",
"max_speed": 100,
"current_speed": 100
"max_speed": 56000,
"current_speed": 56000,
"driver": "mlx4_en",
"bus_info": "0000:22:00.0"
},
{
"name": "eth5",
"mac": "52:54:00:0e:b8:fa",
"max_speed": 100,
"current_speed": 100
"current_speed": 100,
"driver": "igb",
"bus_info": "0000:23:00.0"
}
],
"disks": [
@ -1066,14 +1112,18 @@
"netmask": "255.255.255.240",
"mac": "00:25:90:6a:b1:84",
"max_speed": 1000,
"current_speed": 1000
"current_speed": 1000,
"driver": "igb",
"bus_info": "0000:24:00.0"
},
{
"ip": "10.20.0.7",
"mac": "00:25:90:6a:b1:b5",
"max_speed": 1000,
"name": "p2p2",
"current_speed": null
"current_speed": null,
"driver": "igb",
"bus_info": "0000:25:00.0"
}
],
"disks": [

View File

@ -459,6 +459,8 @@ class NetworkManager(object):
"max_speed": nic.max_speed,
"current_speed": nic.current_speed,
"type": nic.type,
"driver": nic.driver,
"bus_info": nic.bus_info,
}
if to_assign_ids:
@ -793,6 +795,8 @@ class NetworkManager(object):
interface.ip_addr = interface_attrs.get('ip')
interface.netmask = interface_attrs.get('netmask')
interface.state = interface_attrs.get('state')
interface.driver = interface_attrs.get('driver')
interface.bus_info = interface_attrs.get('bus_info')
if interface_attrs.get('interface_properties'):
interface.interface_properties = \
interface_attrs['interface_properties']

View File

@ -57,7 +57,9 @@ class NodeInterfacesSerializer(BasicSerializer):
'state',
'current_speed',
'max_speed',
'assigned_networks'
'assigned_networks',
'driver',
'bus_info',
)
bond_fields = (
'mac',

View File

@ -1269,8 +1269,66 @@ class NeutronNetworkDeploymentSerializer61(
node.cluster.id).count() > 1:
cls.generate_routes(node, attrs, nm, netgroup_mapping, netgroups)
attrs = cls.generate_driver_information(node, attrs, nm)
return attrs
@classmethod
def generate_driver_information(cls, node, network_scheme, nm):
network_mapping = network_scheme.get('roles', {})
endpoints = network_scheme.get('endpoints', {})
bonds_map = dict((b.name, b) for b in node.bond_interfaces)
net_name_mapping = {'ex': 'public'}
managed_networks = ['public', 'storage', 'management']
# Add interfaces drivers data
for iface in node.nic_interfaces:
if iface.driver or iface.bus_info:
iface_dict = network_scheme['interfaces'][iface.name]
if 'vendor_specific' not in iface_dict:
iface_dict['vendor_specific'] = {}
if iface.driver:
iface_dict['vendor_specific']['driver'] = iface.driver
if iface.bus_info:
iface_dict['vendor_specific']['bus_info'] = iface.bus_info
# Add physical allocation data
for ngname, brname in six.iteritems(network_mapping):
if ngname in net_name_mapping:
ngname = net_name_mapping[ngname]
if ngname not in managed_networks:
continue
if 'vendor_specific' not in endpoints[brname]:
endpoints[brname]['vendor_specific'] = {}
netgroup = nm.get_node_network_by_netname(node, ngname)
ep_dict = endpoints[brname]['vendor_specific']
ep_dict['phy_interfaces'] = \
cls.get_phy_interfaces(bonds_map, netgroup)
if netgroup['vlan'] > 1:
ep_dict['vlans'] = netgroup['vlan']
if node.cluster.network_config.segmentation_type == 'vlan':
private_ep = endpoints[network_mapping['neutron/private']]
join_range = lambda r: (":".join(map(str, r)) if r else None)
netgroup = nm.get_node_network_by_netname(node, 'private')
phys = cls.get_phy_interfaces(bonds_map, netgroup)
if 'vendor_specific' not in private_ep:
private_ep['vendor_specific'] = {}
private_ep['vendor_specific']['phy_interfaces'] = phys
private_ep['vendor_specific']['vlans'] = \
join_range(node.cluster.network_config.vlan_range)
return network_scheme
@classmethod
def get_phy_interfaces(cls, bonds_map, netgroup):
if netgroup['dev'] in bonds_map.keys():
phys = [s['name'] for s in bonds_map[netgroup['dev']].slaves]
else:
phys = [netgroup['dev']]
return phys
class GraphBasedSerializer(object):

View File

@ -17,6 +17,7 @@
import copy
from operator import attrgetter
from operator import itemgetter
from random import randint
import re
import six
@ -2460,3 +2461,95 @@ class TestDeploymentHASerializer61(BaseDeploymentSerializer61):
def test_generate_vmware_attributes_data(self):
self.check_generate_vmware_attributes_data()
class TestSerializeInterfaceDriversData(BaseIntegrationTest):
def setUp(self):
super(TestSerializeInterfaceDriversData, self).setUp()
def _create_cluster_for_interfaces(self, driver_mapping={},
bus_mapping={},
segment_type='gre'):
meta = {
'interfaces': [
{'name': 'eth0', 'mac': self.env.generate_random_mac(),
'driver': driver_mapping.get('eth0', 'igb'),
'bus_info': bus_mapping.get('eth0', '0000:05:00.0')},
{'name': 'eth1', 'mac': self.env.generate_random_mac(),
'driver': driver_mapping.get('eth1', 'mlx4_en'),
'bus_info': bus_mapping.get('eth1', '0000:06:00.0')}
]
}
cluster = self.env.create(
cluster_kwargs={
'net_provider': 'neutron',
'net_segment_type': segment_type
},
nodes_kwargs=[
{'roles': ['controller'], 'pending_addition': True,
'meta': meta}
]
)
self.serializer = DeploymentHASerializer61(cluster)
cluster_db = self.db.query(Cluster).get(cluster['id'])
objects.NodeCollection.prepare_for_deployment(cluster_db.nodes)
return cluster_db
def test_interface_driver_bus_info(self):
driver_mapping = {'eth0': 'igb',
'eth1': 'eth_ipoib'}
bus_mapping = {'eth0': '0000:01:00.0',
'eth1': 'ib1'}
cluster = \
self._create_cluster_for_interfaces(driver_mapping, bus_mapping)
self.db.commit()
cluster_db = self.db.query(Cluster).get(cluster['id'])
node = self.serializer.serialize_node(cluster_db.nodes[0],
'controller')
interfaces = node['network_scheme']['interfaces']
for iface, iface_attrs in interfaces.items():
self.assertIn('vendor_specific', iface_attrs)
self.assertIn('driver', iface_attrs['vendor_specific'])
self.assertEqual(iface_attrs['vendor_specific']['driver'],
driver_mapping[iface])
self.assertIn('bus_info', iface_attrs['vendor_specific'])
self.assertEqual(iface_attrs['vendor_specific']['bus_info'],
bus_mapping[iface])
def test_interface_mapping(self):
cluster = self._create_cluster_for_interfaces(segment_type='vlan')
network_group = self.db().query(NetworkGroup)
public_vlan = randint(0, 4095)
storage_vlan = randint(0, 4095)
management_vlan = randint(0, 4095)
private_vlan_range = [randint(0, 4095), randint(0, 4095)]
vlan_mapping = {'ex': public_vlan,
'storage': storage_vlan,
'management': management_vlan,
'neutron/private': "%s:%s" % (private_vlan_range[0],
private_vlan_range[1])}
cluster.network_config["vlan_range"] = private_vlan_range
network_group.filter_by(name="storage").update(
{"vlan_start": storage_vlan}, synchronize_session="fetch")
network_group.filter_by(name="management").update(
{"vlan_start": management_vlan}, synchronize_session="fetch")
network_group.filter_by(name="public").update(
{"vlan_start": public_vlan}, synchronize_session="fetch")
self.db.commit()
cluster_db = self.db.query(Cluster).get(cluster['id'])
node = self.serializer.serialize_node(cluster_db.nodes[0],
'controller')
endpoints = node['network_scheme']['endpoints']
net_roles = node['network_scheme']['roles']
for net_role, bridge in net_roles.items():
ep_dict = endpoints[bridge]
if net_role in vlan_mapping.keys():
self.assertIn('vendor_specific', ep_dict.keys())
self.assertIn('phy_interfaces',
ep_dict['vendor_specific'].keys())
self.assertIn('vlans', ep_dict['vendor_specific'].keys())
self.assertEqual(ep_dict['vendor_specific']['vlans'],
vlan_mapping[net_role])

View File

@ -567,7 +567,7 @@ function($, _, i18n, Backbone, React, utils, models, dispatcher, controls, compo
groups = _.sortBy(_.keys(meta), function(group) {return _.indexOf(groupOrder, group)}),
sortOrder = {
disks: ['name', 'model', 'size'],
interfaces: ['name', 'mac', 'state', 'ip', 'netmask', 'current_speed', 'max_speed']
interfaces: ['name', 'mac', 'state', 'ip', 'netmask', 'current_speed', 'max_speed', 'driver', 'bus_info']
};
return (
<div>