Beispiel #1
0
def step_impl(context):
    for row in context.table.rows:
        amb_props = {context.table.headings[i]: v for i, v in enumerate(row)}

        for num_prop in ["degrees", "rate", "pause_at"]:
            amb_props[num_prop] = int(amb_props[num_prop])

        ISystemEnvironment.set_ambient_props(amb_props)
Beispiel #2
0
def step_impl(context, temp):

    old_ambient = ISystemEnvironment.get_ambient()

    if not math.isclose(temp, old_ambient):
        ISystemEnvironment.set_ambient(temp)
        context.engine.handle_ambient_update(old_ambient, temp)
        context.tracker.wait_thermal_queue()
Beispiel #3
0
def step_impl(context, new_volt):

    old_volt = ISystemEnvironment.get_voltage()
    ISystemEnvironment.set_voltage(new_volt)

    context.engine.handle_voltage_update(old_voltage=old_volt,
                                         new_voltage=new_volt)

    # wait for completion of event loop
    if new_volt != old_volt:
        logging.info(context.tracker.wait_load_queue())
Beispiel #4
0
    def _parents_available(self):
        """Indicates whether a state action can be performed;
        checks if parent nodes are up & running and all OIDs indicate 'on' status

        Returns:
            bool: True if parents are available
        """

        asset_keys, oid_keys = GraphReference.get_parent_keys(
            self._graph_ref.get_session(), self._asset_key
        )

        # if wall-powered, check the mains
        if not asset_keys and not ISystemEnvironment.power_source_available():
            return False

        state_managers = list(map(self.get_state_manager_by_key, asset_keys))
        min_volt_value = self.min_voltage_prop()

        # check if power is present
        enough_voltage = len(
            list(filter(lambda sm: sm.output_voltage > min_volt_value, state_managers))
        )
        parent_assets_up = len(list(filter(lambda sm: sm.status, state_managers)))

        oid_clause = (
            lambda rvalue, rkey: rvalue.split(b"|")[1].decode()
            == oid_keys[rkey]["switchOff"]
        )
        oids_on = self._check_parents(oid_keys.keys(), oid_clause)

        return (parent_assets_up and enough_voltage and oids_on) or (not asset_keys)
Beispiel #5
0
    def on_input_voltage_down(self, event, *args, **kwargs):
        """React to input voltage drop;
        UPS can transfer to battery if in-voltage is low or
        it can transfer back to input power if volt dropped from
        too high to acceptable;
        """

        asset_event = event.get_next_power_event(self)
        asset_event.out_volt.old = self.state.output_voltage

        battery_level = self.state.battery_level
        should_transfer, reason = self.state.process_voltage(event.in_volt.new)

        upstream_load_change = self._get_ups_load_update(should_transfer)
        if upstream_load_change:
            asset_event.load.old, asset_event.load.new = upstream_load_change

        high_line_t_reason = self.state.InputLineFailCause.highLineVoltage

        # voltage is low, transfer to battery
        if should_transfer and self.state.battery_level:
            self._launch_battery_drain(reason)
            asset_event.out_volt.new = ISystemEnvironment.wallpower_volt_standard(
            )

        # voltage was too high but is okay now
        elif (self.state.transfer_reason == high_line_t_reason
              and reason != high_line_t_reason):
            self._launch_battery_charge(power_up_on_charge=(not battery_level))
        else:
            asset_event.calc_load_from_volt()
            self._update_load(self.state.load + asset_event.load.difference)

        return asset_event
Beispiel #6
0
    def _cpu_impact(self):
        """Keep updating *this sensor based on cpu load changes
        This function waits for the thermal event switch and exits when the connection between this sensor & cpu load
        is removed;
        """

        # avoid circular imports with the server
        from enginecore.state.api import IBMCServerStateManager

        with self._graph_ref.get_session() as session:

            asset_info = GraphReference.get_asset_and_components(
                session, self._server_key)
            server_sm = IBMCServerStateManager(asset_info)

            cpu_impact_degrees_1 = 0
            cpu_impact_degrees_2 = 0

            while True:
                self._s_thermal_event.wait()

                rel_details = GraphReference.get_cpu_thermal_rel(
                    session, self._server_key, self.name)

                # relationship was deleted
                if not rel_details:
                    return

                with self._s_file_locks.get_lock(self.name):

                    current_cpu_load = server_sm.cpu_load

                    # calculate cpu impact based on the model
                    cpu_impact_degrees_2 = self._calc_approx_value(
                        json.loads(rel_details["model"]), current_cpu_load)
                    new_calc_value = (int(self.sensor_value) +
                                      cpu_impact_degrees_2 -
                                      cpu_impact_degrees_1)

                    # meaning update is needed
                    if cpu_impact_degrees_1 != cpu_impact_degrees_2:
                        ambient = ISystemEnvironment.get_ambient()
                        self.sensor_value = (new_calc_value
                                             if new_calc_value > ambient else
                                             int(ambient))

                        logger.debug(
                            "Thermal impact of CPU load at (%s%%) updated: (%s°)->(%s°)",
                            current_cpu_load,
                            cpu_impact_degrees_1,
                            cpu_impact_degrees_2,
                        )

                    cpu_impact_degrees_1 = cpu_impact_degrees_2
                    time.sleep(5)
Beispiel #7
0
    def on_input_voltage_up(self, event, *args, **kwargs):
        """React to input voltage spike;
        UPS can transfer to battery if in-voltage is too high;
        It can also transfer back to input power if voltage level is
        within the acceptable threshold;
        """
        asset_event = event.get_next_power_event(self)
        asset_event.out_volt.old = self.state.output_voltage
        asset_event.calc_load_from_volt()

        # process voltage, see if tranfer to battery is needed
        should_transfer, reason = self.state.process_voltage(event.in_volt.new)

        upstream_load_change = self._get_ups_load_update(should_transfer)
        if upstream_load_change:
            asset_event.load.old, asset_event.load.new = upstream_load_change

        # transfer back to input power if ups was running on battery
        if not should_transfer and self.state.on_battery:
            battery_level = self.state.battery_level
            self._launch_battery_charge(power_up_on_charge=(not battery_level))
            if battery_level:
                asset_event.state.new = self.state.power_up()

        # if already on battery (& should stay so), stop voltage propagation
        elif self.state.on_battery:
            asset_event.out_volt.new = asset_event.out_volt.old

        # voltage is too high, transfer to battery
        if should_transfer and reason == self.state.InputLineFailCause.highLineVoltage:
            self._launch_battery_drain(reason)
            asset_event.out_volt.new = ISystemEnvironment.wallpower_volt_standard(
            )

        if not math.isclose(asset_event.load.new, 0) and not math.isclose(
                asset_event.load.new, self.state.load):
            self._update_load(self.state.load + asset_event.load.difference)

        return asset_event
Beispiel #8
0
    def _target_sensor(self, target, event):
        """Keep updating the target sensor based on the relationship between this sensor and the target;
        This function waits for the thermal event switch and exits when the connection between source & target
        is removed;
        Args:
            target(str): name of the target sensor
            event(str): name of the event that enables thermal impact
        """

        with self._graph_ref.get_session() as session:
            while True:

                self._s_thermal_event.wait()

                rel_details = GraphReference.get_sensor_thermal_rel(
                    session,
                    self._server_key,
                    relationship={
                        "source": self.name,
                        "target": {
                            "attribute": "name",
                            "value": '"{}"'.format(target)
                        },
                        "event": event,
                    },
                )

                # shut down thread upon relationship removal
                if not rel_details:
                    del self._th_sensor_t[target][event]
                    return

                rel = rel_details["rel"]
                causes_heating = rel["action"] == "increase"

                source_sensor_status = (operator.eq if rel["event"] == "down"
                                        else operator.ne)
                bound_op = operator.lt if causes_heating else operator.gt
                arith_op = operator.add if causes_heating else operator.sub

                # if model is specified -> use the runtime mappings
                if "model" in rel and rel["model"]:

                    calc_new_sv = arith_op
                    arith_op = lambda sv, _: calc_new_sv(
                        sv,
                        self._calc_approx_value(json.loads(rel["model"]),
                                                int(self.sensor_value) * 10),
                    )

                    source_sensor_status = operator.ne

                # verify that sensor value doesn't go below room temp
                if causes_heating or rel[
                        "pauseAt"] > ISystemEnvironment.get_ambient():
                    pause_at = rel["pauseAt"]
                else:
                    pause_at = ISystemEnvironment.get_ambient()

                # update target sensor value
                with self._s_file_locks.get_lock(target), open(
                        os.path.join(self._s_dir, target), "r+") as sf_handler:

                    current_value = int(sf_handler.read())

                    change_by = (int(rel["degrees"])
                                 if "degrees" in rel and rel["degrees"] else 0)
                    new_sensor_value = arith_op(current_value, change_by)

                    # Source sensor status activated thermal impact
                    if source_sensor_status(int(self.sensor_value), 0):
                        needs_update = bound_op(new_sensor_value, pause_at)
                        if not needs_update and bound_op(
                                current_value, pause_at):
                            needs_update = True
                            new_sensor_value = int(pause_at)

                        if needs_update:
                            logger.info(
                                "Current sensor value (%s°) will be updated to %s°",
                                current_value,
                                int(new_sensor_value),
                            )

                            sf_handler.seek(0)
                            sf_handler.truncate()
                            sf_handler.write(str(new_sensor_value))

                time.sleep(int(rel["rate"]))
Beispiel #9
0
    def _target_storage(self, controller, target, hd_type, event):
        with self._graph_ref.get_session() as session:
            while True:

                self._s_thermal_event.wait()

                # target
                if hd_type == HDComponents.CacheVault:
                    target_attr = "serialNumber"
                    target_value = '"{}"'.format(target)
                elif hd_type == HDComponents.PhysicalDrive:
                    target_attr = "DID"
                    target_value = target
                else:
                    raise ValueError("Unknown hardware component!")

                rel_details = GraphReference.get_sensor_thermal_rel(
                    session,
                    self._server_key,
                    relationship={
                        "source": self._s_name,
                        "target": {
                            "attribute": target_attr,
                            "value": target_value
                        },
                        "event": event,
                    },
                )

                if not rel_details:
                    del self._th_storage_t[target][event]
                    return

                rel = rel_details["rel"]
                causes_heating = rel["action"] == "increase"
                source_sensor_status = (operator.eq if rel["event"] == "down"
                                        else operator.ne)

                # if model is specified -> use the runtime mappings
                if "model" in rel and rel["model"]:
                    rel["degrees"] = self._calc_approx_value(
                        json.loads(rel["model"]),
                        int(self.sensor_value) * 10)

                    source_sensor_status = operator.ne

                if source_sensor_status(int(self.sensor_value), 0):
                    updated, new_temp = GraphReference.add_to_hd_component_temperature(
                        session,
                        target={
                            "server_key": self._server_key,
                            "controller": controller,
                            "attribute": target_attr,
                            "value": target_value,
                            "hd_type": hd_type.name,
                        },
                        temp_change=rel["degrees"] *
                        1 if causes_heating else -1,
                        limit={
                            "lower": ISystemEnvironment.get_ambient(),
                            "upper":
                            rel["pauseAt"] if causes_heating else None,
                        },
                    )

                    if updated:
                        logger.info("temperature sensor was updated to %s°",
                                    new_temp)

                time.sleep(rel["rate"])
Beispiel #10
0
def step_impl(_, temp):
    ambient = ISystemEnvironment.get_ambient()
    assert_that(ambient, equal_to(temp))
Beispiel #11
0
def step_impl(_, temp, delay):
    time.sleep(delay)
    ambient = ISystemEnvironment.get_ambient()
    assert_that(ambient, equal_to(temp))
Beispiel #12
0
def step_impl(context):

    if not ISystemEnvironment.mains_status():
        ISystemEnvironment.power_restore()
        context.engine.handle_voltage_update(old_voltage=0, new_voltage=120)
        logging.info(context.tracker.wait_load_queue())