'Gets a more complete representation of the instance network info.
This data is exposed as network_data.json in the metadata service and
the config drive.
:param node: The node object.
:param network_info: Instance network information.'

def _get_network_metadata(self, node, network_info):

    base_metadata = netutils.get_network_metadata(network_info)
    ports = self.ironicclient.call('node.list_ports', node.uuid, detail=True)
    portgroups = self.ironicclient.call('portgroup.list', node=node.uuid, detail=True)
    vif_id_to_objects = {'ports': {}, 'portgroups': {}}
    for (collection, name) in ((ports, 'ports'), (portgroups, 'portgroups')):
        for p in collection:
            vif_id = (p.internal_info.get('tenant_vif_port_id') or p.extra.get('vif_port_id'))
            if vif_id:
                vif_id_to_objects[name][vif_id] = p
    additional_links = []
    for link in base_metadata['links']:
        vif_id = link['vif_id']
        if (vif_id in vif_id_to_objects['portgroups']):
            pg = vif_id_to_objects['portgroups'][vif_id]
            pg_ports = [p for p in ports if (p.portgroup_uuid == pg.uuid)]
            link.update({'type': 'bond', 'bond_mode': pg.mode, 'bond_links': []})
            if pg.address:
                link.update({'ethernet_mac_address': pg.address})
            for prop in pg.properties:
                key = (prop if prop.startswith('bond') else ('bond_%s' % prop))
                link[key] = pg.properties[prop]
            for port in pg_ports:
                additional_links.append({'id': port.uuid, 'type': 'phy', 'ethernet_mac_address': port.address})
                link['bond_links'].append(port.uuid)
        elif (vif_id in vif_id_to_objects['ports']):
            p = vif_id_to_objects['ports'][vif_id]
            link.update({'ethernet_mac_address': p.address, 'type': 'phy'})
    base_metadata['links'].extend(additional_links)
    return base_metadata
