Compares virtual machine current and new configuration, the current is the
    one which is deployed now, and the new is the target config. Returns the
    differences between the objects in a dictionary, the keys are the
    configuration parameter keys and the values are differences objects: either
    list or recursive difference

    new_config:
        New config dictionary with every available parameter

    current_config
        Currently deployed configuration

def compare_vm_configs(new_config, current_config):
    '''
    Compares virtual machine current and new configuration, the current is the
    one which is deployed now, and the new is the target config. Returns the
    differences between the objects in a dictionary, the keys are the
    configuration parameter keys and the values are differences objects: either
    list or recursive difference

    new_config:
        New config dictionary with every available parameter

    current_config
        Currently deployed configuration
    '''
    diffs = {}
    keys = set(new_config.keys())

    # These values identify the virtual machine, comparison is unnecessary
    keys.discard('name')
    keys.discard('datacenter')
    keys.discard('datastore')
    for property_key in ('version', 'image'):
        if property_key in keys:
            single_value_diff = recursive_diff(
                {property_key: current_config[property_key]},
                {property_key: new_config[property_key]})
            if single_value_diff.diffs:
                diffs[property_key] = single_value_diff
            keys.discard(property_key)

    if 'cpu' in keys:
        keys.remove('cpu')
        cpu_diff = recursive_diff(current_config['cpu'], new_config['cpu'])
        if cpu_diff.diffs:
            diffs['cpu'] = cpu_diff

    if 'memory' in keys:
        keys.remove('memory')
        _convert_units([current_config['memory']])
        _convert_units([new_config['memory']])
        memory_diff = recursive_diff(current_config['memory'],
                                     new_config['memory'])
        if memory_diff.diffs:
            diffs['memory'] = memory_diff

    if 'advanced_configs' in keys:
        keys.remove('advanced_configs')
        key = 'advanced_configs'
        advanced_diff = recursive_diff(current_config[key], new_config[key])
        if advanced_diff.diffs:
            diffs[key] = advanced_diff

    if 'disks' in keys:
        keys.remove('disks')
        _convert_units(current_config['disks'])
        _convert_units(new_config['disks'])
        disk_diffs = list_diff(current_config['disks'],
                               new_config['disks'],
                               'address')
        # REMOVE UNSUPPORTED DIFFERENCES/CHANGES
        # If the disk already exist, the backing properties like eagerly scrub
        # and thin provisioning
        # cannot be updated, and should not be identified as differences
        disk_diffs.remove_diff(diff_key='eagerly_scrub')
        # Filename updates are not supported yet, on VSAN datastores the
        # backing.fileName points to a uid + the vmdk name
        disk_diffs.remove_diff(diff_key='filename')
        # The adapter name shouldn't be changed
        disk_diffs.remove_diff(diff_key='adapter')
        if disk_diffs.diffs:
            diffs['disks'] = disk_diffs

    if 'interfaces' in keys:
        keys.remove('interfaces')
        interface_diffs = list_diff(current_config['interfaces'],
                                    new_config['interfaces'], 'mac')
        # The adapter name shouldn't be changed
        interface_diffs.remove_diff(diff_key='adapter')
        if interface_diffs.diffs:
            diffs['interfaces'] = interface_diffs

    # For general items where the identification can be done by adapter
    for key in keys:
        if key not in current_config or key not in new_config:
            raise ValueError('A general device {0} configuration was '
                             'not supplied or it was not retrieved from '
                             'remote configuration'.format(key))
        device_diffs = list_diff(current_config[key],
                                 new_config[key],
                                 'adapter')
        if device_diffs.diffs:
            diffs[key] = device_diffs

    return diffs