示例#1
0
def test_is_sstbf_configured():
    class SYS:
        def __init__(self, configured):
            self.sst_bf_configured = configured

        def refresh_stats(self):
            return

    with mock.patch("pwr.get_system",
                    return_value=SYS(True)) as mock_get_system:
        assert sstbf.is_sstbf_configured()
        mock_get_system.assert_called_once()

    with mock.patch("pwr.get_system",
                    return_value=SYS(False)) as mock_get_system:
        assert not sstbf.is_sstbf_configured()
        mock_get_system.assert_called_once()

    with mock.patch("pwr.get_system", return_value=None) as mock_get_system:
        assert not sstbf.is_sstbf_configured()
        mock_get_system.assert_called_once()

    with mock.patch("pwr.get_system", return_value=[]) as mock_get_system:
        assert not sstbf.is_sstbf_configured()
        mock_get_system.assert_called_once()

    with mock.patch("pwr.get_system",
                    side_effect=IOError('Test')) as mock_get_system:
        assert not sstbf.is_sstbf_configured()
        mock_get_system.assert_called_once()
示例#2
0
    def event_handler(self):
        """
        Handles config_changed event
        """

        # rate limiting
        last_cfg_change_ts = 0
        min_time_diff = 1 / common.RATE_LIMIT

        while not self.stop_event.is_set():
            if common.CONFIG_STORE.is_config_changed():

                time_diff = time.time() - last_cfg_change_ts
                if time_diff < min_time_diff:
                    log.info("Rate Limiter, sleeping " \
                        + str(round((min_time_diff - time_diff) * 1000)) + "ms...")
                    time.sleep(min_time_diff - time_diff)

                log.info("Configuration changed, processing new config...")
                result = cache_ops.configure_rdt()
                if result != 0:
                    log.error("Failed to apply RDT configuration!")
                    break

                if caps.sstcp_enabled() and not sstbf.is_sstbf_configured():
                    result = power.configure_power()
                    if result != 0:
                        log.error(
                            "Failed to apply Power Profiles configuration!")
                        break

                last_cfg_change_ts = time.time()
                log.info("New configuration processed")
示例#3
0
    def func_wrapper(*args, **kwargs):
        if not _get_power_profiles_expert_mode():
            raise MethodNotAllowed("Please enable Expert Mode first.")

        if sstbf.is_sstbf_configured():
            raise MethodNotAllowed(
                "SST-BF configured, please un-configure SST-BF first")

        return f(*args, **kwargs)
示例#4
0
    def post():
        """
        Handles HTTP POST /pools request.
        Add a new Pool
        Raises NotFound, BadRequest, InternalError

        Returns:
            response, status code
        """
        json_data = request.get_json()

        # validate pool schema
        try:
            schema, resolver = ConfigStore.load_json_schema('add_pool.json')
            jsonschema.validate(json_data, schema, resolver=resolver)
        except jsonschema.ValidationError as error:
            raise BadRequest("Request validation failed - %s" % (str(error)))

        admission_control_check = json_data.pop('verify', True) and\
            ('cores' in json_data or 'power_profile' in json_data)

        post_data = json_data.copy()
        post_data['id'] = common.CONFIG_STORE.get_new_pool_id(post_data)
        if post_data['id'] is None:
            raise InternalError("New POOL not added, maximum number of POOLS"\
                " reached for requested allocation combination")

        # convert cbm from string to int
        if 'cbm' in post_data:
            cbm = post_data['cbm']
            if not isinstance(cbm, int):
                cbm = int(cbm, 16)

            post_data['cbm'] = cbm

        # ignore 'power_profile' if SST-BF is enabled
        if sstbf.is_sstbf_configured():
            post_data.pop('power_profile', None)

        data = deepcopy(common.CONFIG_STORE.get_config())
        data['pools'].append(post_data)

        try:
            common.CONFIG_STORE.validate(data, admission_control_check)
        except Exception as ex:
            raise BadRequest("New POOL not added, " + str(ex))

        common.CONFIG_STORE.set_config(data)

        res = {
            'id': post_data['id'],
            'message': "New POOL {} added".format(post_data['id'])
        }
        return res, 201
示例#5
0
    def get():
        """
        Handles HTTP GET /caps/sstbf request.
        Retrieve SST-BF capabilities details

        Returns:
            response, status code
        """
        res = {
            'configured': sstbf.is_sstbf_configured(),
            'hp_cores': sstbf.get_hp_cores(),
            'std_cores': sstbf.get_std_cores()
        }
        return res, 200
示例#6
0
def configure_power():
    """
    Configures Power Profiles
    """

    global PREV_PROFILES

    # we do not configure power profiles is SST-BF is enabled
    if sstbf.is_sstbf_configured():
        PREV_PROFILES = {}
        return 0

    curr_profiles = _get_curr_profiles()
    if curr_profiles is None:
        return -1

    if not curr_profiles:
        return 0

    # has power profiles configuration changed since last run?
    if PREV_PROFILES == curr_profiles:
        return 0

    # in case there was a change, find out which profiles has been changed
    for profile in curr_profiles.values():
        if not profile['cores']:
            continue

        prev_profile = PREV_PROFILES.get(profile['id'], [])

        # apply configuration only for changed profiles
        if prev_profile != profile:
            log.debug("POWER: Power profile {} configuration...".format(
                profile['id']))
            min_freq = profile.get('min_freq', None)
            max_freq = profile.get('max_freq', None)
            epp = profile.get('epp', None)
            _set_freqs_epp(profile['cores'], min_freq, max_freq, epp)

    # reset power config for cores with no power profile assigned
    cores_to_reset = _get_cores_to_reset()
    if cores_to_reset:
        reset(cores_to_reset)

    # save current profiles configuration
    PREV_PROFILES = curr_profiles

    return 0
示例#7
0
def test_is_sstbf_configured():
    class CPU:
        def __init__(self, configured):
            self.sst_bf_configured = configured
            self.core_list = []

        def refresh_stats(self, core=None):
            return

    with mock.patch("pwr.get_cpus", return_value=[CPU(True),
                                                  CPU(True)]) as mock_get_cpus:
        assert sstbf.is_sstbf_configured()
        mock_get_cpus.assert_called_once()

    with mock.patch("pwr.get_cpus",
                    return_value=[CPU(True), CPU(False)]) as mock_get_cpus:
        assert not sstbf.is_sstbf_configured()
        mock_get_cpus.assert_called_once()

    with mock.patch("pwr.get_cpus",
                    return_value=[CPU(False), CPU(False)]) as mock_get_cpus:
        assert not sstbf.is_sstbf_configured()
        mock_get_cpus.assert_called_once()

    with mock.patch("pwr.get_cpus", return_value=None) as mock_get_cpus:
        assert not sstbf.is_sstbf_configured()
        mock_get_cpus.assert_called_once()

    with mock.patch("pwr.get_cpus", return_value=[]) as mock_get_cpus:
        assert not sstbf.is_sstbf_configured()
        mock_get_cpus.assert_called_once()

    with mock.patch("pwr.get_cpus",
                    side_effect=IOError('Test')) as mock_get_cpus:
        assert not sstbf.is_sstbf_configured()
        mock_get_cpus.assert_called_once()
示例#8
0
def _do_admission_control_check():
    """
    Admission control check is done if
    - SST-BF is not configured
    """
    return not sstbf.is_sstbf_configured()
示例#9
0
    def run(self):
        """
        Runs main loop.
        """

        # process/validate already loaded config file
        try:
            common.CONFIG_STORE.process_config()
        except Exception as ex:
            log.error("Invalid config file... ")
            log.error(ex)
            return

        log.debug("Cores controlled: {}".\
            format(common.CONFIG_STORE.get_pool_attr('cores', None)))

        data = common.CONFIG_STORE.get_config()
        for pool in data['pools']:
            log.debug("Pool: {}/{} Cores: {}, Apps: {}".format(pool.get('name'),\
                pool.get('id'), pool.get('cores'), pool.get('apps')))

        # set initial SST-BF configuration
        if caps.sstbf_enabled():
            result = sstbf.init_sstbf()
            if result != 0:
                log.error(
                    "Failed to apply initial SST-BF configuration, terminating..."
                )
                return

            log.info("SST-BF enabled, {}configured.".\
                format("not " if not sstbf.is_sstbf_configured() else ""))
            log.info("SST-BF HP cores: {}".format(sstbf.get_hp_cores()))
            log.info("SST-BF STD cores: {}".format(sstbf.get_std_cores()))
        else:
            log.info("SST-BF not enabled")

        # set initial SST-CP configuration if SST-BF is not configured
        if caps.sstcp_enabled():
            if sstbf.is_sstbf_configured():
                log.info(
                    "Power Profiles/SST-CP enabled, not configured, SST-BF is configured"
                )
            else:
                log.info("Power Profiles/SST-CP enabled.")
                # set initial POWER configuration
                result = power.configure_power()
                if result != 0:
                    log.error("Failed to apply initial Power Profiles configuration,"\
                        " terminating...")
                    return
        else:
            log.info("Power Profiles/EPP not enabled")

        # set initial RDT configuration
        log.info("Configuring RDT")

        # Configure MBA CTRL
        if caps.mba_supported():
            result = common.PQOS_API.enable_mba_bw(
                common.CONFIG_STORE.get_mba_ctrl_enabled())
            if result != 0:
                log.error(
                    "libpqos MBA CTRL initialization failed, Terminating...")
                return
            log.info("RDT MBA CTRL %sabled"\
                % ("en" if common.PQOS_API.is_mba_bw_enabled() else "dis"))

        result = cache_ops.configure_rdt()
        if result != 0:
            log.error(
                "Failed to apply initial RDT configuration, terminating...")
            return

        # set CTRL+C sig handler
        signal.signal(signal.SIGINT, self.signal_handler)

        self.event_handler()

        log.info("Terminating...")
示例#10
0
    def put(pool_id):
        # pylint: disable=too-many-branches
        """
        Handles HTTP PUT /pools/<pool_id> request.
        Modifies a Pool
        Raises NotFound, BadRequest

        Parameters:
            pool_id: Id of pool

        Returns:
            response, status code
        """
        def check_alloc_tech(pool_id, json_data):
            if 'cbm' in json_data:
                if not caps.cat_supported():
                    raise BadRequest("System does not support CAT!")
                if pool_id > common.PQOS_API.get_max_cos_id([common.CAT_CAP]):
                    raise BadRequest(
                        "Pool {} does not support CAT".format(pool_id))

            if 'mba' in json_data:
                if not caps.mba_supported():
                    raise BadRequest("System does not support MBA!")
                if pool_id > common.PQOS_API.get_max_cos_id([common.MBA_CAP]):
                    raise BadRequest(
                        "Pool {} does not support MBA".format(pool_id))

        json_data = request.get_json()

        # validate app schema
        try:
            schema, resolver = ConfigStore.load_json_schema('modify_pool.json')
            jsonschema.validate(json_data, schema, resolver=resolver)
        except jsonschema.ValidationError as error:
            raise BadRequest("Request validation failed - %s" % (str(error)))

        admission_control_check = json_data.pop('verify', True) and\
            ('cores' in json_data or 'power_profile' in json_data)

        data = deepcopy(common.CONFIG_STORE.get_config())
        if 'pools' not in data:
            raise NotFound("No pools in config file")

        for pool in data['pools']:
            if pool['id'] != int(pool_id):
                continue

            check_alloc_tech(int(pool_id), json_data)

            # set new cbm
            if 'cbm' in json_data:
                cbm = json_data['cbm']
                if not isinstance(cbm, int):
                    cbm = int(cbm, 16)

                pool['cbm'] = cbm

            # set new mba
            if 'mba' in json_data:
                pool['mba'] = json_data['mba']

            # set new cores
            if 'cores' in json_data:
                pool['cores'] = json_data['cores']

            if 'apps' in pool and pool['apps']:
                for app_id in pool['apps']:
                    for app in data['apps']:
                        if app['id'] != app_id or 'cores' not in app:
                            continue
                        if not set(app['cores']).issubset(pool['cores']):
                            app.pop('cores')

            # set new name
            if 'name' in json_data:
                pool['name'] = json_data['name']

            # set new power profile
            # ignore 'power_profile' if SST-BF is enabled
            if 'power_profile' in json_data and not sstbf.is_sstbf_configured(
            ):
                pool['power_profile'] = json_data['power_profile']

            try:
                common.CONFIG_STORE.validate(data, admission_control_check)
            except Exception as ex:
                raise BadRequest("POOL " + str(pool_id) + " not updated, " +
                                 str(ex))

            common.CONFIG_STORE.set_config(data)

            res = {'message': "POOL " + str(pool_id) + " updated"}
            return res, 200

        raise NotFound("POOL " + str(pool_id) + " not found in config")
示例#11
0
    def run(self, args):
        """
        Runs main loop.

        Parameters:
            args: command line arguments
        """

        # load config file
        try:
            common.CONFIG_STORE.from_file(args.config)
        except IOError as ex:
            log.error("Error reading from config file {}... ".format(args.config))
            log.error(ex)
            return
        except Exception as ex:
            log.error("Invalid config file {}... ".format(args.config))
            log.error(ex)
            return

        log.debug("Cores controlled: {}".\
            format(common.CONFIG_STORE.get_pool_attr('cores', None)))

        data = common.CONFIG_STORE.get_config()
        for pool in data['pools']:
            log.debug("Pool: {}/{} Cores: {}, Apps: {}".format(pool.get('name'),\
                pool.get('id'), pool.get('cores'), pool.get('apps')))

        # set initial SST-BF configuration
        if caps.sstbf_enabled():
            result = sstbf.init_sstbf()
            if result != 0:
                log.error("Failed to apply initial SST-BF configuration, terminating...")
                return

            log.info("SST-BF enabled, {}configured.".\
                format("not " if not sstbf.is_sstbf_configured() else ""))
            log.info("SST-BF HP cores: {}".format(sstbf.get_hp_cores()))
            log.info("SST-BF STD cores: {}".format(sstbf.get_std_cores()))
        else:
            log.info("SST-BF not enabled")

        # set initial SST-CP configuration if SST-BF is not configured
        if caps.sstcp_enabled():
            if sstbf.is_sstbf_configured():
                log.info("Power Profiles/SST-CP enabled, not configured, SST-BF is configured")
            else:
                log.info("Power Profiles/SST-CP enabled.")
                # set initial POWER configuration
                result = power.configure_power()
                if result != 0:
                    log.error("Failed to apply initial Power Profiles configuration,"\
                        " terminating...")
                    return
        else:
            log.info("Power Profiles/EPP not enabled")

        # set initial RDT configuration
        log.info("Configuring RDT")
        result = cache_ops.configure_rdt()
        if result != 0:
            log.error("Failed to apply initial RDT configuration, terminating...")
            return

        # set CTRL+C sig handler
        signal.signal(signal.SIGINT, self.signal_handler)

        self.event_handler()

        log.info("Terminating...")