Manage the SNMP accepted community names and their permissions.

    .. note::
        Settings managed by Group Policy will always take precedence over those
        set using the SNMP interface. Therefore if this function finds Group
        Policy settings it will raise a CommandExecutionError

    Args:
        communities (dict): A dictionary of SNMP community names and
            permissions. The possible permissions can be found via
            ``win_snmp.get_permission_types``.

    Returns:
        bool: True if successful, otherwise False

    Raises:
        CommandExecutionError:
            If SNMP settings are being managed by Group Policy

    CLI Example:

    .. code-block:: bash

        salt '*' win_snmp.set_community_names communities="{'TestCommunity': 'Read Only'}'

def set_community_names(communities):
    '''
    Manage the SNMP accepted community names and their permissions.

    .. note::
        Settings managed by Group Policy will always take precedence over those
        set using the SNMP interface. Therefore if this function finds Group
        Policy settings it will raise a CommandExecutionError

    Args:
        communities (dict): A dictionary of SNMP community names and
            permissions. The possible permissions can be found via
            ``win_snmp.get_permission_types``.

    Returns:
        bool: True if successful, otherwise False

    Raises:
        CommandExecutionError:
            If SNMP settings are being managed by Group Policy

    CLI Example:

    .. code-block:: bash

        salt '*' win_snmp.set_community_names communities="{'TestCommunity': 'Read Only'}'
    '''
    values = dict()

    if __utils__['reg.key_exists'](_HKEY, _COMMUNITIES_GPO_KEY):
        _LOG.debug('Communities on this system are managed by Group Policy')
        raise CommandExecutionError(
            'Communities on this system are managed by Group Policy')

    current_communities = get_community_names()

    if communities == current_communities:
        _LOG.debug('Communities already contain the provided values.')
        return True

    for vname in communities:
        if not communities[vname]:
            communities[vname] = 'None'
        try:
            vdata = _PERMISSION_TYPES[communities[vname]]
        except KeyError:
            message = (
                "Invalid permission '{0}' specified. Valid permissions: "
                "{1}").format(communities[vname], _PERMISSION_TYPES.keys())
            raise SaltInvocationError(message)
        values[vname] = vdata

    # Check current communities.
    for current_vname in current_communities:
        if current_vname in values:
            # Modify existing communities that have a different permission value.
            if current_communities[current_vname] != values[current_vname]:
                __utils__['reg.set_value'](
                    _HKEY, _COMMUNITIES_KEY, current_vname,
                    values[current_vname], 'REG_DWORD')
        else:
            # Remove current communities that weren't provided.
            __utils__['reg.delete_value'](
                _HKEY, _COMMUNITIES_KEY, current_vname)

    # Create any new communities.
    for vname in values:
        if vname not in current_communities:
            __utils__['reg.set_value'](
                _HKEY, _COMMUNITIES_KEY, vname, values[vname], 'REG_DWORD')

    # Get the fields post-change so that we can verify tht all values
    # were modified successfully. Track the ones that weren't.
    new_communities = get_community_names()
    failed_communities = dict()

    for new_vname in new_communities:
        if new_vname not in communities:
            failed_communities[new_vname] = None

    for vname in communities:
        if communities[vname] != new_communities[vname]:
            failed_communities[vname] = communities[vname]

    if failed_communities:
        _LOG.error('Unable to configure communities: %s', failed_communities)
        return False
    _LOG.debug('Communities configured successfully: %s', communities.keys())
    return True