'Builds a metadata object for instance devices, that maps the user
provided tag to the hypervisor assigned device address.'

def _build_device_metadata(self, context, instance):

    def _get_device_name(bdm):
        return block_device.strip_dev(bdm.device_name)
    network_info = instance.info_cache.network_info
    vlans_by_mac = netutils.get_cached_vifs_with_vlan(network_info)
    vifs = objects.VirtualInterfaceList.get_by_instance_uuid(context, instance.uuid)
    vifs_to_expose = {vif.address: vif for vif in vifs if ((('tag' in vif) and vif.tag) or vlans_by_mac.get(vif.address))}
    bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(context, instance.uuid)
    tagged_bdms = {_get_device_name(bdm): bdm for bdm in bdms if bdm.tag}
    devices = []
    guest = self._host.get_guest(instance)
    xml = guest.get_xml_desc()
    xml_dom = etree.fromstring(xml)
    guest_config = vconfig.LibvirtConfigGuest()
    guest_config.parse_dom(xml_dom)
    for dev in guest_config.devices:
        if isinstance(dev, vconfig.LibvirtConfigGuestInterface):
            vif = vifs_to_expose.get(dev.mac_addr)
            if (not vif):
                continue
            bus = self._prepare_device_bus(dev)
            device = objects.NetworkInterfaceMetadata(mac=vif.address)
            if (('tag' in vif) and vif.tag):
                device.tags = [vif.tag]
            if bus:
                device.bus = bus
            vlan = vlans_by_mac.get(vif.address)
            if vlan:
                device.vlan = int(vlan)
            devices.append(device)
        if isinstance(dev, vconfig.LibvirtConfigGuestDisk):
            bdm = tagged_bdms.get(dev.target_dev)
            if (not bdm):
                continue
            bus = self._prepare_device_bus(dev)
            device = objects.DiskMetadata(tags=[bdm.tag])
            device.serial = bdm.volume_id
            if bus:
                device.bus = bus
            devices.append(device)
    if devices:
        dev_meta = objects.InstanceDeviceMetadata(devices=devices)
        return dev_meta
