Merge "Add 'meta' to bond properties"

This commit is contained in:
Jenkins 2017-01-12 11:13:01 +00:00 committed by Gerrit Code Review
commit 7531738dcf
3 changed files with 141 additions and 1 deletions

View File

@ -22,6 +22,7 @@ from nailgun.extensions.network_manager.objects.interface import DPDKMixin
from nailgun.extensions.network_manager.objects.interface import NIC
from nailgun.objects import NailgunCollection
from nailgun.objects import NailgunObject
from nailgun.objects import Release
from nailgun.objects.serializers.base import BasicSerializer
from nailgun.plugins.manager import PluginManager
from nailgun import utils
@ -72,7 +73,7 @@ class Bond(DPDKMixin, NailgunObject):
@classmethod
def dpdk_available(cls, instance, dpdk_drivers):
return all(NIC.get_dpdk_driver(iface, dpdk_drivers)
return all(NIC.dpdk_available(iface, dpdk_drivers)
for iface in instance.slaves)
@classmethod
@ -105,6 +106,76 @@ class Bond(DPDKMixin, NailgunObject):
return attributes
@classmethod
def get_meta(cls, instance):
"""Get immutable attributes for bond.
:param instance: NodeBondInterface instance
:type instance: NodeBondInterface model
:returns: dict -- Object of bond attributes
"""
meta = {}
dpdk_drivers = Release.get_supported_dpdk_drivers(
instance.node.cluster.release)
meta['dpdk'] = {
'available': cls.dpdk_available(instance, dpdk_drivers)}
meta['offloading'] = {
'modes': Bond.get_available_offloading_modes(instance)
}
return meta
@classmethod
def get_available_offloading_modes(cls, instance):
"""Get available offloading modes for bond.
This method collects information about available offloading modes
for each slave interface and returns their intersection.
:param instance: NodeBondInterface instance
:type instance: NodeBondInterface model
:returns: list -- Available offloading modes
"""
structure = None
intersection_dict = {}
for interface in instance.slaves:
modes = interface.meta['offloading_modes']
if structure is None:
structure = copy.deepcopy(modes)
intersection_dict = \
NIC.offloading_modes_as_flat_dict(structure)
continue
intersection_dict = cls._intersect_offloading_dicts(
intersection_dict,
NIC.offloading_modes_as_flat_dict(modes)
)
return cls._apply_intersection(structure, intersection_dict)
@staticmethod
def _intersect_offloading_dicts(dict1, dict2):
result = dict()
for mode in dict1:
if mode in dict2:
if dict1[mode] is None or dict2[mode] is None:
result[mode] = None
else:
result[mode] = dict1[mode] and dict2[mode]
return result
@classmethod
def _apply_intersection(cls, modes, intersection_dict):
result = list()
if modes is None:
return result
for mode in modes:
if mode["name"] not in intersection_dict:
continue
mode["state"] = intersection_dict[mode["name"]]
if mode["sub"]:
mode["sub"] = \
cls._apply_intersection(mode["sub"], intersection_dict)
result.append(mode)
return result
@classmethod
def get_default_attributes(cls, cluster):
"""Get native and plugin default attributes for bond.

View File

@ -104,6 +104,7 @@ class NodeInterfacesSerializer(BasicSerializer):
data_dict = BasicSerializer.serialize(instance, fields=fields)
data_dict['slaves'] = [{'name': s.name} for s in instance.slaves]
data_dict['attributes'] = Bond.get_attributes(instance)
data_dict['meta'] = Bond.get_meta(instance)
return data_dict

View File

@ -121,6 +121,74 @@ class TestBondObject(BaseTestCase):
self.env.clusters[0])
self.assertEqual(len(bond_interfaces), 1)
def check_offloading_modes_intersection(self, modes_1, modes_2,
expected_result):
data = {
'name': 'bond0',
'slaves': self.node.nic_interfaces,
'node': self.node
}
bond = objects.Bond.create(data)
self.node.nic_interfaces[0].meta['offloading_modes'] = modes_1
self.node.nic_interfaces[1].meta['offloading_modes'] = modes_2
self.assertEquals(
objects.Bond.get_available_offloading_modes(bond),
expected_result)
def test_get_available_offloading_modes(self):
different_modes = [
[{
'name': 'mode_for_nic1',
'state': None,
'sub': [
{
'name': 'sub_mode_for_nic1',
'state': False,
'sub': []
}
]
}],
[{
'name': 'mode_for_nic2',
'state': True,
'sub': []
}],
]
self.check_offloading_modes_intersection(different_modes[0],
different_modes[1],
[])
common_mode = {'name': 'common_mode', 'state': True, 'sub': []}
for modes in different_modes:
modes.append(common_mode)
self.check_offloading_modes_intersection(different_modes[0],
different_modes[1],
[common_mode])
common_mode_2 = {
'name': 'common_mode_2',
'state': True, 'sub': [
{
'name': 'common_sub',
'state': False,
'sub': []
}
]}
for i, modes in enumerate(different_modes):
mode = copy.deepcopy(common_mode_2)
mode['sub'].append({'name': 'uncommon_sub_{}'.format(i),
'state': None,
'sub': []})
modes.append(mode)
self.check_offloading_modes_intersection(different_modes[0],
different_modes[1],
[common_mode, common_mode_2])
class TestNICObject(BaseTestCase):