diff --git a/api/src/opentrons/config/advanced_settings.py b/api/src/opentrons/config/advanced_settings.py index f4c88626e4d..feebbe1cb48 100644 --- a/api/src/opentrons/config/advanced_settings.py +++ b/api/src/opentrons/config/advanced_settings.py @@ -17,7 +17,6 @@ ) from opentrons.config import CONFIG, ARCHITECTURE, SystemArchitecture -from opentrons.system import log_control from opentrons_shared_data.robot.dev_types import RobotTypeEnum if TYPE_CHECKING: @@ -109,22 +108,6 @@ def __init__(self) -> None: robot_type=[RobotTypeEnum.OT2, RobotTypeEnum.FLEX], ) - async def on_change(self, value: Optional[bool]) -> None: - """Special side effect for this setting""" - if ARCHITECTURE == SystemArchitecture.BUILDROOT: - code, stdout, stderr = await log_control.set_syslog_level( - "emerg" if value else "info" - ) - if code != 0: - log.error( - f"Could not set log control: {code}: stdout={stdout}" - f" stderr={stderr}" - ) - raise SettingException( - f"Failed to set log upstreaming: {code}", "log-config-failure" - ) - await super().on_change(value) - class Setting(NamedTuple): value: Optional[bool] diff --git a/api/src/opentrons/system/log_control.py b/api/src/opentrons/system/log_control.py index 507822e3fbc..bd44af3c7c2 100644 --- a/api/src/opentrons/system/log_control.py +++ b/api/src/opentrons/system/log_control.py @@ -7,7 +7,7 @@ import asyncio import logging import subprocess -from typing import Tuple, List +from typing import List LOG = logging.getLogger(__name__) @@ -53,36 +53,3 @@ async def get_records_dumb(selector: str, records: int, mode: str) -> bytes: ) stdout, _ = await proc.communicate() return stdout - - -async def set_syslog_level(level: str) -> Tuple[int, str, str]: - """ - Set the minimum level for which logs will be sent upstream via syslog-ng. - - This is the function that actually does the work for - :py:meth:`set_syslog_level_handler`. - - Similar to :py:meth:`opentrons.server.endpoints.settings.set_log_level`, - the level should be a python log level like "debug", "info", "warning", or - "error". If it is null, sets the minimum log level to emergency which we - do not log at since there's not really a matching level in python logging, - which effectively disables log upstreaming. - - :returns tuple(int, str, str): The error code, stdout, and stderr from - ``syslog-ng-ctl``. ``0`` is success, - anything else is failure - """ - with open("/var/lib/syslog-ng/min-level", "w") as ml: - ml.write(level) - proc = await asyncio.create_subprocess_exec( - "syslog-ng-ctl", - "reload", - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - ) - stdout, stderr = await proc.communicate() - if proc.returncode is None: - snc_reload_result = -1 - else: - snc_reload_result: int = proc.returncode # type: ignore - return snc_reload_result, stdout.decode(), stderr.decode() diff --git a/api/tests/opentrons/config/test_advanced_settings.py b/api/tests/opentrons/config/test_advanced_settings.py index 21140b0f3d7..606d691b1a9 100644 --- a/api/tests/opentrons/config/test_advanced_settings.py +++ b/api/tests/opentrons/config/test_advanced_settings.py @@ -1,9 +1,9 @@ import pytest from pytest_lazyfixture import lazy_fixture # type: ignore[import] -from typing import Any, Dict, Generator, Optional, Tuple +from typing import Dict, Generator, Optional from unittest.mock import MagicMock, patch -from opentrons.config import advanced_settings, ARCHITECTURE, CONFIG +from opentrons.config import advanced_settings, CONFIG from opentrons_shared_data.robot.dev_types import RobotTypeEnum @@ -253,47 +253,6 @@ async def test_restart_required( assert advanced_settings.is_restart_required() is True -@pytest.mark.parametrize( - argnames=["v", "expected_level"], - argvalues=[ - [True, "emerg"], - [False, "info"], - ], -) -async def test_disable_log_integration_side_effect( - v: bool, expected_level: str -) -> None: - with patch("opentrons.config.advanced_settings.log_control") as mock_log_control: - - async def set_syslog_level(level: Any) -> Tuple[int, str, str]: - return 0, "", "" - - mock_log_control.set_syslog_level.side_effect = set_syslog_level - with patch( - "opentrons.config.advanced_settings.ARCHITECTURE", - new=ARCHITECTURE.BUILDROOT, - ): - s = advanced_settings.DisableLogIntegrationSettingDefinition() - await s.on_change(v) - mock_log_control.set_syslog_level.assert_called_once_with(expected_level) - - -async def test_disable_log_integration_side_effect_error() -> None: - with patch("opentrons.config.advanced_settings.log_control") as mock_log_control: - - async def set_syslog_level(level: Any) -> Tuple[int, str, str]: - return 1, "", "" - - mock_log_control.set_syslog_level.side_effect = set_syslog_level - with patch( - "opentrons.config.advanced_settings.ARCHITECTURE", - new=ARCHITECTURE.BUILDROOT, - ): - s = advanced_settings.DisableLogIntegrationSettingDefinition() - with pytest.raises(advanced_settings.SettingException): - await s.on_change(True) - - def test_per_robot_true_defaults(mock_read_settings_file_empty: MagicMock) -> None: with patch.object(advanced_settings, "settings_by_id", new={}): assert ( diff --git a/robot-server/robot_server/service/legacy/routers/settings.py b/robot-server/robot_server/service/legacy/routers/settings.py index dc9c08b293d..290f16c546d 100644 --- a/robot-server/robot_server/service/legacy/routers/settings.py +++ b/robot-server/robot_server/service/legacy/routers/settings.py @@ -11,7 +11,6 @@ dev_types as hardware_dev_types, ) from opentrons.hardware_control.types import HardwareFeatureFlags -from opentrons.system import log_control from opentrons_shared_data.pipette import ( mutable_configurations, types as pip_types, @@ -36,7 +35,6 @@ from robot_server.service.legacy.models.settings import ( AdvancedSettingsResponse, LogLevel, - LogLevels, FactoryResetOptions, PipetteSettings, PipetteSettingsUpdate, @@ -167,47 +165,17 @@ async def post_log_level_local( path="/settings/log_level/upstream", description=( "Set the minimum level of logs sent upstream via" - " syslog-ng to Opentrons. Only available on" - " a real robot." + " syslog-ng to Opentrons." + " Removed in robot software v7.2.0." ), - response_model=V1BasicResponse, - responses={ - status.HTTP_500_INTERNAL_SERVER_ERROR: {"model": LegacyErrorResponse}, - }, + response_model=LegacyErrorResponse, + deprecated=True, ) async def post_log_level_upstream(log_level: LogLevel) -> V1BasicResponse: - log_level_value = log_level.log_level - log_level_name = None if log_level_value is None else log_level_value.name - ok_syslogs = { - LogLevels.error.name: "err", - LogLevels.warning.name: "warning", - LogLevels.info.name: "info", - LogLevels.debug.name: "debug", - } - - syslog_level = "emerg" - if log_level_name is not None: - syslog_level = ok_syslogs[log_level_name] - - code, stdout, stderr = await log_control.set_syslog_level(syslog_level) - - if code != 0: - msg = f"Could not reload config: {stdout} {stderr}" - log.error(msg) - raise LegacyErrorResponse( - message=msg, errorCode=ErrorCodes.GENERAL_ERROR.value.code - ).as_error( - status.HTTP_500_INTERNAL_SERVER_ERROR, - ) - - if log_level_name: - result = f"Upstreaming log level changed to {log_level_name}" - getattr(log, log_level_name)(result) - else: - result = "Upstreaming logs disabled" - log.info(result) - - return V1BasicResponse(message=result) + raise LegacyErrorResponse( + message="API Discontinued - log streaming removed", + errorCode=str(ErrorCodes.API_REMOVED), + ).as_error(status.HTTP_410_GONE) @router.get( diff --git a/robot-server/tests/service/legacy/routers/test_settings.py b/robot-server/tests/service/legacy/routers/test_settings.py index dbe99c2ba09..b4fe6e380a3 100644 --- a/robot-server/tests/service/legacy/routers/test_settings.py +++ b/robot-server/tests/service/legacy/routers/test_settings.py @@ -26,52 +26,6 @@ from robot_server.persistence import PersistenceResetter, get_persistence_resetter -# TODO(isk: 3/20/20): test validation errors after refactor -# return {message: string} -@pytest.mark.parametrize( - "log_level, syslog_level, expected_message", - [ - ("error", "err", {"message": "Upstreaming log level changed to error"}), - ("ERROR", "err", {"message": "Upstreaming log level changed to error"}), - ("warning", "warning", {"message": "Upstreaming log level changed to warning"}), - ("WARNING", "warning", {"message": "Upstreaming log level changed to warning"}), - ("info", "info", {"message": "Upstreaming log level changed to info"}), - ("INFO", "info", {"message": "Upstreaming log level changed to info"}), - ("debug", "debug", {"message": "Upstreaming log level changed to debug"}), - ("DEBUG", "debug", {"message": "Upstreaming log level changed to debug"}), - (None, "emerg", {"message": "Upstreaming logs disabled"}), - (None, "emerg", {"message": "Upstreaming logs disabled"}), - ], -) -def test_post_log_level_upstream(api_client, log_level, syslog_level, expected_message): - with patch("opentrons.system.log_control.set_syslog_level") as m: - m.return_value = 0, "stdout", "stderr" - response = api_client.post( - "/settings/log_level/upstream", json={"log_level": log_level} - ) - body = response.json() - assert response.status_code == 200 - assert body == expected_message - m.assert_called_once_with(syslog_level) - - -def test_post_log_level_upstream_fails_reload(api_client): - log_level = "debug" - - with patch("opentrons.system.log_control.set_syslog_level") as m: - m.return_value = 1, "stdout", "stderr" - response = api_client.post( - "/settings/log_level/upstream", json={"log_level": log_level} - ) - body = response.json() - assert response.status_code == 500 - assert body == { - "message": "Could not reload config: stdout stderr", - "errorCode": "4000", - } - m.assert_called_once_with(log_level) - - def test_get_robot_settings(api_client, hardware): Conf = make_dataclass("Conf", ["a", "b", "c"]) hardware.config = Conf(a="test", b="this", c=5)