Add 'meta' to bond properties
Dynamically generate 'meta' for bond and put there information about DPDK availability and structure of available offloading modes. Change-Id: Id030dda19b150b56db5624bd45c8f767d0748a47 Closes-bug: #1652068
This commit is contained in:
parent
1e0d9278a2
commit
13be8e85c1
|
@ -21,6 +21,7 @@ from nailgun.objects.interface import DPDKMixin
|
|||
from nailgun.objects import NailgunCollection
|
||||
from nailgun.objects import NailgunObject
|
||||
from nailgun.objects import NIC
|
||||
from nailgun.objects import Release
|
||||
from nailgun.objects.serializers.base import BasicSerializer
|
||||
from nailgun.plugins.manager import PluginManager
|
||||
from nailgun import utils
|
||||
|
@ -65,6 +66,64 @@ 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):
|
||||
structure = None
|
||||
intersection_dict = {}
|
||||
for interface in instance.slaves:
|
||||
modes = interface.meta['offloading_modes']
|
||||
if structure is None:
|
||||
structure = 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:
|
||||
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 copy.deepcopy(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_bond_default_attributes(cls, cluster):
|
||||
"""Get native and plugin default attributes for bond.
|
||||
|
@ -100,7 +159,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)
|
||||
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ class DPDKMixin(object):
|
|||
@classmethod
|
||||
def refresh_interface_dpdk_properties(cls, interface, dpdk_drivers):
|
||||
attributes = interface.attributes
|
||||
meta = interface.meta
|
||||
dpdk_attributes = copy.deepcopy(attributes.get('dpdk', {}))
|
||||
dpdk_available = cls.dpdk_available(interface, dpdk_drivers)
|
||||
|
||||
|
|
|
@ -140,6 +140,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
|
||||
|
||||
|
|
|
@ -2197,6 +2197,74 @@ class TestBondObject(BaseTestCase):
|
|||
objects.Bond.update(bond, copy.deepcopy(new_data))
|
||||
self.assertEqual(new_data['attributes'], bond['attributes'])
|
||||
|
||||
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):
|
||||
|
||||
|
|
Loading…
Reference in New Issue