'Build a tree of devices that represents parent-child relationships.
We need to have the relationships set up so that we can easily make
all the necessary changes to parent/child devices without having to
figure it out at each call site.
This method just adds references to relevant instances already found
in `pci_devs` to `child_devices` and `parent_device` fields of each
one.
Currently relationships are considered for SR-IOV PFs/VFs only.'

@staticmethod
def _build_device_tree(all_devs):

    all_devs.sort(key=(lambda x: x.address))
    parents = {}
    for dev in all_devs:
        if (dev.status in (fields.PciDeviceStatus.REMOVED, fields.PciDeviceStatus.DELETED)):
            continue
        if (dev.dev_type == fields.PciDeviceType.SRIOV_PF):
            dev.child_devices = []
            parents[dev.address] = dev
        elif (dev.dev_type == fields.PciDeviceType.SRIOV_VF):
            dev.parent_device = parents.get(dev.parent_addr)
            if dev.parent_device:
                parents[dev.parent_addr].child_devices.append(dev)
