<commit_before>#!/usr/bin/env python3
#
#  Copyright (c) 2015 - 2021, Intel Corporation
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#
#      * Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#
#      * Redistributions in binary form must reproduce the above copyright
#        notice, this list of conditions and the following disclaimer in
#        the documentation and/or other materials provided with the
#        distribution.
#
#      * Neither the name of Intel Corporation nor the names of its
#        contributors may be used to endorse or promote products derived
#        from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

"""Module containing the implementations of the DBus interfaces
exposed by geopmd."""

import os
import pwd
import grp
import json
import shutil
import psutil
import gi
from gi.repository import GLib

from . import pio
from . import topo
from dasbus.connection import SystemMessageBus
try:
    from dasbus.server.interface import accepts_additional_arguments
except ImportError as ee:
    err_msg = '''dasbus version greater than 1.5 required:
    https://github.com/rhinstaller/dasbus/pull/57'''
    raise ImportError(err_msg) from ee

class PlatformService(object):
    """Provides the concrete implementation for all of the GEOPM DBus
    interfaces that use PlatformIO.  This class is used by the
    GEOPMService class that maps DBus interfaces to their
    implementations.

    """
    def __init__(self):
        """PlatformService constructor that initializes all private members.

        """
        self._pio = pio
        self._CONFIG_PATH = '/etc/geopm-service'
        self._VAR_PATH = '/var/run/geopm-service'
        self._ALL_GROUPS = [gg.gr_name for gg in grp.getgrall()]
        self._DEFAULT_ACCESS = '0.DEFAULT_ACCESS'
        self._SAVE_DIR = 'SAVE_FILES'
        self._WATCH_INTERVAL_MSEC = 1000
        self._write_pid = None
        self._sessions = dict()

    def get_group_access(self, group):
        """Get the signals and controls in the allowed lists.

        Provides the default allowed lists or the allowed lists for a
        particular Unix group.  These lists correspond to values
        stored in the GEOPM service configuration files.  The
        configuration files are read with each call to this method.
        If no files exist that match the query, empty lists are
        returned.  Empty lines and lines that begin with the '#'
        character are ignored.  If the group name is not valid on the
        system a RuntimeError is raised.

        Args:
            group (str): Unix group name to query. The default allowed
                lists are returned if group is the empty string.

        Returns:
            list(str), list(str): Signal and control allowed lists

        """
        group = self._validate_group(group)
        group_dir = os.path.join(self._CONFIG_PATH, group)
        if os.path.isdir(group_dir):
            path = os.path.join(group_dir, 'allowed_signals')
            signals = self._read_allowed(path)
            path = os.path.join(group_dir, 'allowed_controls')
            controls = self._read_allowed(path)
        else:
            signals = []
            controls = []
        return signals, controls

    def set_group_access(self, group, allowed_signals, allowed_controls):
        """Set the signals and controls in the allowed lists.

        Writes the configuration files that control the default
        allowed lists or the allowed lists for a particular Unix
        group.  These lists restrict user access to signals or
        controls provided by the service.  If the user specifies a
        list that contains signals or controls that are not currently
        supported, the request will raise a RuntimeError without
        modifying any configuration files.  A RuntimeError will also
        be raised if the group name is not valid on the system.

        Args:
            group (str): Which Unix group name to query; if this is
                         the empty string, the default allowed
                         lists are written.

            allowed_signals (list(str)): Signal names that are allowed

            allowed_controls (list(str)): Control names that are allowed

        """
        group = self._validate_group(group)
        self._validate_signals(allowed_signals)
        self._validate_controls(allowed_controls)
        group_dir = os.path.join(self._CONFIG_PATH, group)
        os.makedirs(group_dir, exist_ok=True)
        path = os.path.join(group_dir, 'allowed_signals')
        self._write_allowed(path, allowed_signals)
        path = os.path.join(group_dir, 'allowed_controls')
        self._write_allowed(path, allowed_controls)

    def get_user_access(self, user):
        """Get the list of all of the signals and controls that are
        accessible to the specified user, or the default access lists
        that apply to all non-root users if the empty string is
        provided.

        All available signals and controls are returned if the caller
        specifies the user name 'root'.  A RuntimeError is
        raised if the user does not exist on the system.

        When a user requests a signal or control through one of the
        other PlatformService methods, they are restricted to the
        union of the default allowed lists and the allowed lists for<commit_msg>Conforming to google style for the docstring for the get_user_access method.<commit_after>#!/usr/bin/env python3
#
#  Copyright (c) 2015 - 2021, Intel Corporation
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#
#      * Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#
#      * Redistributions in binary form must reproduce the above copyright
#        notice, this list of conditions and the following disclaimer in
#        the documentation and/or other materials provided with the
#        distribution.
#
#      * Neither the name of Intel Corporation nor the names of its
#        contributors may be used to endorse or promote products derived
#        from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

"""Module containing the implementations of the DBus interfaces
exposed by geopmd."""

import os
import pwd
import grp
import json
import shutil
import psutil
import gi
from gi.repository import GLib

from . import pio
from . import topo
from dasbus.connection import SystemMessageBus
try:
    from dasbus.server.interface import accepts_additional_arguments
except ImportError as ee:
    err_msg = '''dasbus version greater than 1.5 required:
    https://github.com/rhinstaller/dasbus/pull/57'''
    raise ImportError(err_msg) from ee

class PlatformService(object):
    """Provides the concrete implementation for all of the GEOPM DBus
    interfaces that use PlatformIO.  This class is used by the
    GEOPMService class that maps DBus interfaces to their
    implementations.

    """
    def __init__(self):
        """PlatformService constructor that initializes all private members.

        """
        self._pio = pio
        self._CONFIG_PATH = '/etc/geopm-service'
        self._VAR_PATH = '/var/run/geopm-service'
        self._ALL_GROUPS = [gg.gr_name for gg in grp.getgrall()]
        self._DEFAULT_ACCESS = '0.DEFAULT_ACCESS'
        self._SAVE_DIR = 'SAVE_FILES'
        self._WATCH_INTERVAL_MSEC = 1000
        self._write_pid = None
        self._sessions = dict()

    def get_group_access(self, group):
        """Get the signals and controls in the allowed lists.

        Provides the default allowed lists or the allowed lists for a
        particular Unix group.  These lists correspond to values
        stored in the GEOPM service configuration files.  The
        configuration files are read with each call to this method.
        If no files exist that match the query, empty lists are
        returned.  Empty lines and lines that begin with the '#'
        character are ignored.  If the group name is not valid on the
        system a RuntimeError is raised.

        Args:
            group (str): Unix group name to query. The default allowed
                lists are returned if group is the empty string.

        Returns:
            list(str), list(str): Signal and control allowed lists

        """
        group = self._validate_group(group)
        group_dir = os.path.join(self._CONFIG_PATH, group)
        if os.path.isdir(group_dir):
            path = os.path.join(group_dir, 'allowed_signals')
            signals = self._read_allowed(path)
            path = os.path.join(group_dir, 'allowed_controls')
            controls = self._read_allowed(path)
        else:
            signals = []
            controls = []
        return signals, controls

    def set_group_access(self, group, allowed_signals, allowed_controls):
        """Set the signals and controls in the allowed lists.

        Writes the configuration files that control the default
        allowed lists or the allowed lists for a particular Unix
        group.  These lists restrict user access to signals or
        controls provided by the service.  If the user specifies a
        list that contains signals or controls that are not currently
        supported, the request will raise a RuntimeError without
        modifying any configuration files.  A RuntimeError will also
        be raised if the group name is not valid on the system.

        Args:
            group (str): Which Unix group name to query; if this is
                         the empty string, the default allowed
                         lists are written.

            allowed_signals (list(str)): Signal names that are allowed

            allowed_controls (list(str)): Control names that are allowed

        """
        group = self._validate_group(group)
        self._validate_signals(allowed_signals)
        self._validate_controls(allowed_controls)
        group_dir = os.path.join(self._CONFIG_PATH, group)
        os.makedirs(group_dir, exist_ok=True)
        path = os.path.join(group_dir, 'allowed_signals')
        self._write_allowed(path, allowed_signals)
        path = os.path.join(group_dir, 'allowed_controls')
        self._write_allowed(path, allowed_controls)

    def get_user_access(self, user):
        """Get the list of all of the signals and controls that are
        accessible to the specified user.

        Returns the default access lists that apply to all non-root
        users if the empty string is provided.

        All available signals and controls are returned if the caller
        specifies the user name 'root'.  A RuntimeError is
        raised if the user does not exist on the system.

        When a user requests a signal or control through one of the
        other PlatformService methods, they are restricted to the
        union of the default allowed lists and the allowed lists for
{'fraction_non_alphanumeric': 0.055629242412421, 'fraction_numerical': 0.0028087696028711866, 'mean_word_length': 2.7788915094339623, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4198778', 'n_tokens_mistral': 3324, 'n_tokens_neox': 3152, 'n_words': 1445}