Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API for swap configuration #5770

Merged
merged 4 commits into from
Mar 27, 2025
Merged

Add API for swap configuration #5770

merged 4 commits into from
Mar 27, 2025

Conversation

sairon
Copy link
Member

@sairon sairon commented Mar 20, 2025

Proposed change

Add HTTP API for swap size and swappiness to /os/config/swap. Individual options can be set in JSON and are calling the DBus API added in OS Agent 1.7.x, available since OS 15.0. Check for presence of OS of the required version and return 404 if the criteria are not met.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality to the supervisor)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Ruff (ruff format supervisor tests)
  • Tests have been added to verify that the new code works.

If API endpoints or add-on configuration are added/changed:

Summary by CodeRabbit

  • New Features

    • Introduced new API endpoints for viewing and adjusting operating system swap configurations.
    • Enhanced system integration allows users to manage swap size and swappiness settings.
  • Tests

    • Added comprehensive tests to validate the functionality of the new swap configuration options.
    • Improved test coverage contributes to overall system reliability and stability.

Copy link
Contributor

coderabbitai bot commented Mar 20, 2025

📝 Walkthrough

Walkthrough

The changes add swap management functionality to the system. New API routes are introduced under /os/config/swap for getting and updating swap settings. In the API layer, additional asynchronous methods and a validation schema are implemented. Corresponding constants for swap attributes are defined in both the core and DBus modules. A new DBus interface for swap configuration is implemented and exposed by the OS agent. Finally, tests have been expanded and updated—including new mocks and fixtures—to verify the behavior of these endpoints and the DBus swap interface under various scenarios.

Changes

File(s) Change Summary
supervisor/api/__init__.py, supervisor/api/os.py, supervisor/const.py Added new API routes (GET and POST at /os/config/swap) and implemented asynchronous methods (config_swap_info, config_swap_options) with validation for managing swap settings. New constants (ATTR_SWAP_SIZE, ATTR_SWAPPINESS) are defined.
supervisor/dbus/agent/__init__.py, supervisor/dbus/agent/swap.py, supervisor/dbus/const.py Introduced a new DBus swap interface. The OSAgent now exposes a swap property backed by the new Swap class, which defines properties and asynchronous setters for swap_size and swappiness. New DBus constants for swap configuration are added.
tests/api/test_os.py, tests/dbus/agent/test_agent.py, tests/dbus/agent/test_swap.py, tests/dbus_service_mocks/agent_swap.py, tests/conftest.py Expanded test coverage for swap configuration. New tests verify API endpoints and DBus interactions under various scenarios, fixtures are updated to include a mock agent_swap service, and a new DBus service mock is added for swap functionality.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant R as RestAPI
    participant A as APIOS
    participant O as OSAgent
    participant S as Swap (DBus)
    
    C->>R: GET /os/config/swap
    R->>A: config_swap_info(request)
    A->>O: Retrieve swap settings
    O->>S: Query swap_size & swappiness
    S-->>O: Return current swap values
    O-->>A: Provide swap info
    A-->>R: Return response data
    R-->>C: 200 OK (swap info)
Loading
sequenceDiagram
    participant C as Client
    participant R as RestAPI
    participant A as APIOS
    participant O as OSAgent
    participant S as Swap (DBus)
    
    C->>R: POST /os/config/swap (payload)
    R->>A: config_swap_options(request)
    A->>O: Validate and apply new swap settings
    O->>S: Update swap_size & swappiness
    S-->>O: Acknowledge update
    O-->>A: Check for reboot requirement
    A-->>R: Return success/issue response
    R-->>C: 200 OK
Loading

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c2455f8 and f814d7d.

📒 Files selected for processing (11)
  • supervisor/api/__init__.py (1 hunks)
  • supervisor/api/os.py (4 hunks)
  • supervisor/const.py (1 hunks)
  • supervisor/dbus/agent/__init__.py (4 hunks)
  • supervisor/dbus/agent/swap.py (1 hunks)
  • supervisor/dbus/const.py (3 hunks)
  • tests/api/test_os.py (2 hunks)
  • tests/conftest.py (1 hunks)
  • tests/dbus/agent/test_agent.py (1 hunks)
  • tests/dbus/agent/test_swap.py (1 hunks)
  • tests/dbus_service_mocks/agent_swap.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • supervisor/dbus/agent/swap.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • tests/conftest.py
  • tests/dbus/agent/test_agent.py
  • supervisor/const.py
  • supervisor/dbus/const.py
  • tests/dbus/agent/test_swap.py
  • tests/dbus_service_mocks/agent_swap.py
🧰 Additional context used
🧬 Code Definitions (2)
supervisor/api/__init__.py (1)
supervisor/api/os.py (2)
  • config_swap_info (229-239)
  • config_swap_options (242-268)
supervisor/dbus/agent/__init__.py (2)
supervisor/dbus/agent/swap.py (1)
  • Swap (15-40)
tests/dbus_service_mocks/agent_swap.py (1)
  • Swap (15-42)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Build armv7 supervisor
  • GitHub Check: Build armhf supervisor
  • GitHub Check: Build aarch64 supervisor
  • GitHub Check: Run tests Python 3.13.2
🔇 Additional comments (18)
supervisor/api/__init__.py (1)

240-241: Route definitions look good.

The new API endpoints for OS swap configuration are properly registered with the correct handlers.

supervisor/dbus/agent/__init__.py (4)

25-25: Import for new Swap class looks good.

The new import needed for the swap functionality is correctly added.


47-47: Correctly initializes the Swap component.

The swap instance is properly initialized in the constructor.


60-64: Good implementation of the swap property.

The property is well-documented and returns the correct private instance.


96-106: Properly includes swap in the list of all dbus interfaces.

The swap property is now correctly included in the all property's return list, which was missing according to PR comments. This ensures that the swap DBus interface is properly managed by methods that rely on the complete list of interfaces, such as connect and shutdown.

supervisor/api/os.py (7)

6-6: Import of re module for pattern matching.

Correctly added import for the regex functionality used later.


25-26: New ATTR constants for swap configuration.

The constants for swap_size and swappiness are properly imported from const.py.


32-32: APINotFound exception import.

Added import for the exception used when the required OS version isn't available.


72-72: Regular expression for swap size validation.

The regex pattern correctly checks for valid swap size formats according to what's permitted in the OS.


74-79: Schema definition for swap options validation.

The validation schema properly enforces:

  1. Swap size matches the defined regex pattern
  2. Swappiness is an integer between 0 and 200

This addresses previous review comments about validation and ensures that only valid configurations can be submitted.


228-239: Well-implemented swap info retrieval.

The method correctly:

  1. Checks OS availability and version compatibility
  2. Raises the appropriate exception with a clear error message
  3. Returns the current swap configuration

Good job on adding the clear error message as suggested in previous reviews.


241-268: Well-implemented swap options update.

The method correctly:

  1. Checks OS availability and version compatibility
  2. Validates the request body against the schema
  3. Updates only the provided options
  4. Correctly determines if a reboot is required using the reboot_required or pattern

The logic for determining if a reboot is required has been fixed as suggested in previous reviews - now it properly accumulates the need for a reboot across both settings.

tests/api/test_os.py (6)

21-21: Added SwapService import for tests.

The new import enables testing of the swap configuration functionality.


343-356: Comprehensive test for swap info API.

Test correctly verifies:

  1. OS version compatibility check (via parametrize)
  2. API response status
  3. Expected response values

Good approach to test the configuration retrieval functionality.


358-422: Thorough tests for swap options API.

Test suite effectively covers:

  1. Setting both swap size and swappiness
  2. Setting only swap size
  3. Setting only swappiness
  4. Verification that proper reboot notifications are created
  5. Verification that values are actually updated in the DBus service

This provides good coverage of the new API's functionality.


424-465: Good tests for the no-reboot scenarios.

Tests verify that no reboot is required when:

  1. Empty options are submitted
  2. Options that match current values are submitted

This ensures the system doesn't request unnecessary reboots.


468-486: Tests for non-OS environment error cases.

Verifies that a 404 error is correctly returned when not running on Home Assistant OS for both GET and POST endpoints.


489-509: Tests for OS version compatibility.

Verifies that a 404 error is correctly returned when running on an OS version below 15.0 for both GET and POST endpoints.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🔭 Outside diff range comments (1)
supervisor/dbus/agent/__init__.py (1)

97-99: ⚠️ Potential issue

Missing swap in the 'all' property.

The all property returns a list of all managed DBUS interfaces, but it doesn't include the newly added self._swap. This could cause issues with methods that rely on this list being complete, such as the connect and shutdown methods.

@property
def all(self) -> list[DBusInterface]:
    """Return all managed dbus interfaces."""
-    return [self.apparmor, self.board, self.cgroup, self.datadisk, self.system]
+    return [self.apparmor, self.board, self.cgroup, self.datadisk, self.system, self.swap]
🧹 Nitpick comments (1)
supervisor/api/os.py (1)

243-256: Consider adding validation for swap parameters

While the schema ensures the proper types, there's no validation for the range of swappiness (typically 0-100) or the format of swap size (e.g., "1M", "2G").

Consider adding additional validation to ensure the provided values are within acceptable ranges:

if ATTR_SWAPPINESS in body:
    swappiness = body[ATTR_SWAPPINESS]
    if not 0 <= swappiness <= 100:
        raise web.HTTPBadRequest(text="Swappiness must be between 0 and 100")
    
if ATTR_SWAP_SIZE in body:
    # Add validation for swap size format if needed
    # For example, ensure it follows the pattern like "1M", "2G", etc.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7f139d and 9007915.

📒 Files selected for processing (11)
  • supervisor/api/__init__.py (1 hunks)
  • supervisor/api/os.py (4 hunks)
  • supervisor/const.py (1 hunks)
  • supervisor/dbus/agent/__init__.py (3 hunks)
  • supervisor/dbus/agent/swap.py (1 hunks)
  • supervisor/dbus/const.py (3 hunks)
  • tests/api/test_os.py (2 hunks)
  • tests/conftest.py (1 hunks)
  • tests/dbus/agent/test_agent.py (1 hunks)
  • tests/dbus/agent/test_swap.py (1 hunks)
  • tests/dbus_service_mocks/agent_swap.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
`*/**(html|markdown|md)`: - For instructional content in documentation, use a direct and authoritative tone. Avoid expressions of politeness such as 'may' or 'please', and ensure t...

*/**(html|markdown|md): - For instructional content in documentation, use a direct and authoritative tone. Avoid expressions of politeness such as 'may' or 'please', and ensure the goal of the instruction is fronted.

  • Apply the Microsoft Style Guide to ensure documentation maintains clarity and conciseness.
  • In step-by-step instructions, front the location phrase in the instructional sentence.
  • In step-by-step instructions, front the 'goal' in the instructional sentence.
  • In step-by-step instructions, if in doubt what to front, front the 'goal' before the location phrase in the instructional sentence.
  • do not hyphenate terms like 'top-right' or 'bottom-left' with 'corner'
  • tests/conftest.py
  • supervisor/const.py
`*/**(html|markdown|md)`: - Use bold to mark UI strings. - If "" are used to mark UI strings, replace them by bold.

*/**(html|markdown|md): - Use bold to mark UI strings.

  • If "" are used to mark UI strings, replace them by bold.
  • tests/conftest.py
  • supervisor/const.py
`*/**(html|markdown|md)`: - Be brief in your replies and don't add fluff like "thank you for..." and "Please let me know if"

*/**(html|markdown|md): - Be brief in your replies and don't add fluff like "thank you for..." and "Please let me know if"

  • tests/conftest.py
  • supervisor/const.py
`*/**(html|markdown|md)`: - Use sentence-style capitalization also in headings.

*/**(html|markdown|md): - Use sentence-style capitalization also in headings.

  • tests/conftest.py
  • supervisor/const.py
`*/**(html|markdown|md)`: do not comment on HTML used for icons

*/**(html|markdown|md): do not comment on HTML used for icons

  • tests/conftest.py
  • supervisor/const.py
`*/**(html|markdown|md)`: Avoid flagging inline HTML for embedding videos in future reviews for this repository.

*/**(html|markdown|md): Avoid flagging inline HTML for embedding videos in future reviews for this repository.

  • tests/conftest.py
  • supervisor/const.py
🧬 Code Definitions (5)
supervisor/api/__init__.py (1)
supervisor/api/os.py (2) (2)
  • config_swap_info (227-235)
  • config_swap_options (238-262)
supervisor/dbus/agent/__init__.py (2)
supervisor/dbus/agent/swap.py (1) (1)
  • Swap (15-40)
tests/dbus_service_mocks/agent_swap.py (1) (1)
  • Swap (15-42)
supervisor/dbus/agent/swap.py (1)
tests/dbus_service_mocks/agent_swap.py (1) (1)
  • Swap (15-42)
tests/dbus_service_mocks/agent_swap.py (1)
supervisor/dbus/agent/swap.py (1) (1)
  • Swap (15-40)
tests/dbus/agent/test_swap.py (4)
supervisor/dbus/agent/__init__.py (3) (3)
  • OSAgent (31-148)
  • swap (61-63)
  • connect (101-124)
supervisor/dbus/agent/swap.py (3) (3)
  • Swap (15-40)
  • swap_size (24-26)
  • swappiness (34-36)
tests/dbus_service_mocks/agent_swap.py (1) (1)
  • Swap (15-42)
tests/conftest.py (1) (1)
  • dbus_session_bus (148-152)
🔇 Additional comments (30)
supervisor/const.py (1)

316-317: LGTM! New attribute constants for swap configuration

The new constants ATTR_SWAP_SIZE and ATTR_SWAPPINESS follow the consistent naming pattern used throughout this file. These will support the new swap configuration API.

supervisor/dbus/const.py (3)

28-28: LGTM! New DBus interface constant for swap configuration

This constant correctly defines the D-Bus interface identifier following the established pattern used for other interfaces.


57-57: LGTM! New DBus object path for swap configuration

This constant correctly defines the D-Bus object path following the same pattern as other object paths in the file.


174-175: LGTM! New DBus attribute constants for swap properties

These constants correctly define the D-Bus attribute names for swap size and swappiness, maintaining the camelCase convention used for D-Bus attributes.

tests/conftest.py (1)

282-282: LGTM! Added mock for agent_swap service

Properly added the mock for the new agent_swap service in the fixture_os_agent_services function, which is necessary for testing the new swap configuration functionality.

tests/dbus/agent/test_agent.py (1)

72-72: LGTM! Added agent_swap mock for connection error testing

Correctly added the agent_swap service to the os_agent_services dictionary in the test_dbus_osagent_connect_error function, ensuring consistent test coverage for the new swap configuration service.

supervisor/api/__init__.py (1)

261-267: New routes added for swap configuration management.

These routes implement the HTTP API for managing swap size and swappiness settings via the /os/config/swap endpoint, which aligns with the PR objectives. The implementation uses the appropriate HTTP methods (GET for retrieving settings, POST for updating them).

supervisor/dbus/agent/__init__.py (3)

25-25: The import of the new Swap class is properly added.

This import statement correctly brings in the newly implemented Swap class from the swap module.


47-47: The Swap instance is initialized properly.

Following the established pattern in this class, a Swap instance is created during initialization.


60-64: The property accessor for Swap is correctly implemented.

The property accessor follows the same pattern as other DBUS objects in this class, providing a clean interface for accessing the swap functionality.

supervisor/dbus/agent/swap.py (3)

1-21: The Swap class implementation follows good practices.

The class is well-structured, with clear docstrings and proper organization of constants and methods. It inherits from DBusInterfaceProxy and properly configures the necessary DBus connection details.


28-31: The set_swap_size method is properly implemented.

This method provides the necessary functionality to set the swap size via DBus, returning an Awaitable for asynchronous operation.


38-40: The set_swappiness method is properly implemented.

This method provides the necessary functionality to set the swappiness value via DBus, returning an Awaitable for asynchronous operation.

tests/dbus_service_mocks/agent_swap.py (4)

1-13: The setup function for the swap mock is implemented correctly.

This function follows the pattern of other mock setup functions, creating and returning an instance of the Swap mock class.


15-23: The Swap mock class is properly configured.

The class properly inherits from DBusServiceMock and sets up the correct object path and interface for mocking the swap configuration DBus service.


24-33: The SwapSize property is properly implemented.

The getter returns a default value of "1M" and the setter correctly emits properties changed signals, which is essential for testing property change notifications.


34-42: The Swappiness property is properly implemented.

The getter returns a default value of 1 and the setter correctly emits properties changed signals when the value is updated.

tests/dbus/agent/test_swap.py (4)

1-11: LGTM: Clear imports and docstring

The module docstring and import organization follow the project's standard structure.


12-17: LGTM: Well-structured fixture

The fixture_swap_service is properly set up to provide the mock swap service from the os_agent_services dictionary, following the project's standard testing pattern.


20-33: LGTM: Thorough swap size test implementation

The test correctly verifies both initial state and property changes for the swap size. The pattern of connecting to the bus, checking initial values, emitting property changes, and verifying the updated values is well-implemented.


36-50: LGTM: Consistent swappiness test implementation

The swappiness test follows the same pattern as the swap size test, ensuring consistent testing methodology across related properties.

supervisor/api/os.py (3)

25-26: LGTM: Added new attributes for swap configuration

The new attributes ATTR_SWAP_SIZE and ATTR_SWAPPINESS are properly imported from the constants module.


72-77: LGTM: Well-defined schema for swap options

The schema properly validates and coerces the swap configuration parameters to their expected types (string for swap size and integer for swappiness).


226-235: LGTM: Implemented swap configuration info endpoint

The implementation correctly checks for OS availability and version compatibility before proceeding. The response includes both swap_size and swappiness values from the DBus agent.

tests/api/test_os.py (6)

21-21: LGTM: Added import for SwapService

The import for the mock SwapService follows the project's import pattern for test mocks.


343-356: LGTM: Well-implemented swap info test

The test properly checks that the API returns the expected swap configuration values, using the parametrized fixture to ensure the test runs with OS version 15.0.


358-422: LGTM: Comprehensive swap options test

This test thoroughly verifies the API's capability to set both swap parameters together and individually. It also checks that reboot issues are correctly created when settings are changed.


424-465: LGTM: Edge case testing for no reboot scenarios

Good coverage of edge cases where no reboot should be required, such as empty settings or unchanged values. This ensures the reboot flag logic works correctly.


468-486: LGTM: Error case testing for non-OS environment

Proper verification that a 404 response is returned when the system is not running on Home Assistant OS.


489-509: LGTM: Version compatibility test

Good test coverage ensuring that the API correctly returns 404 for systems running OS versions older than 15.0, as specified in the requirements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
supervisor/api/os.py (1)

229-230: Consider extracting the version check into a helper method.

Since the version check appears in both methods with identical logic, consider extracting it to a private helper method to avoid code duplication.

@@ -226,6 +226,11 @@
     @api_process
+    def _check_swap_support(self) -> None:
+        """Check if swap management is supported."""
+        if not self.coresys.os.available or self.coresys.os.version < "15.0":
+            raise HTTPNotFound()
+
+    @api_process
     async def config_swap_info(self, request: web.Request) -> dict[str, Any]:
         """Get swap settings."""
-        if not self.coresys.os.available or self.coresys.os.version < "15.0":
-            raise HTTPNotFound()
+        self._check_swap_support()

@@ -237,8 +242,7 @@
     async def config_swap_options(self, request: web.Request) -> None:
         """Update swap settings."""
-        if not self.coresys.os.available or self.coresys.os.version < "15.0":
-            raise HTTPNotFound()
+        self._check_swap_support()

Also applies to: 240-241

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9007915 and 21cd3c6.

📒 Files selected for processing (2)
  • supervisor/api/os.py (4 hunks)
  • supervisor/dbus/agent/swap.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • supervisor/dbus/agent/swap.py
🧰 Additional context used
🧬 Code Definitions (1)
supervisor/api/os.py (2)
supervisor/dbus/agent/__init__.py (2) (2)
  • version (82-84)
  • swap (61-63)
supervisor/dbus/agent/swap.py (4) (4)
  • swap_size (24-26)
  • swappiness (33-35)
  • set_swap_size (27-29)
  • set_swappiness (36-38)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Build armv7 supervisor
  • GitHub Check: Build armhf supervisor
  • GitHub Check: Build aarch64 supervisor
  • GitHub Check: Run tests Python 3.13.2
🔇 Additional comments (6)
supervisor/api/os.py (6)

9-9: HTTPNotFound import is appropriate for the new endpoints.

The import is correctly added to handle cases where OS is not available or doesn't meet the minimum version requirements in the new swap configuration endpoints.


25-26: Attribute constants are properly imported.

These constants are correctly added to the imports to support the new swap configuration functionality.


72-77: Schema definition is well-implemented.

The SCHEMA_SWAP_OPTIONS is correctly defined with proper type coercion for both parameters, making it consistent with other validation schemas in the file.


226-235: Good implementation of the swap info endpoint.

The method correctly:

  1. Checks for OS availability and version compatibility
  2. Returns appropriate HTTP status when requirements aren't met
  3. Returns the current swap configuration values from the DBus agent

237-262: Swap options update logic is well-implemented with proper reboot handling.

The implementation correctly:

  1. Validates OS availability and version requirements
  2. Validates input using the schema
  3. Updates swap settings as needed
  4. Correctly determines if a reboot is required using accumulative logic
  5. Creates a system issue when reboot is required

The reboot logic has been properly fixed as suggested in previous review comments.


229-230:

✅ Verification successful

Verify OS version check logic is consistent with other endpoints.

Both methods use the same check before accessing OS agent functionality. Let's verify this is consistent with how version requirements are handled in other endpoints.

Also applies to: 240-241


🏁 Script executed:

#!/bin/bash
# Check how version requirements are handled in other API methods in the codebase
rg -B3 -A1 "os\.version\s*<" --type py

Length of output: 727


OS Version Check Logic Consistent Across Endpoints
The verification confirms that both endpoints in supervisor/api/os.py (lines 229-230 and 240-241) are using the same check (if not self.coresys.os.available or self.coresys.os.version < "15.0":) before accessing OS agent functionality. No further changes are needed.

Comment on lines 264 to 265
web.get("/os/config/swap", api_os.config_swap_info),
web.post("/os/config/swap", api_os.config_swap_options),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously more of a nitpick but we have /os/config/sync up above, think we should just add these two to the list up here:

web.post("/os/config/sync", api_os.config_sync),

async def config_swap_info(self, request: web.Request) -> dict[str, Any]:
"""Get swap settings."""
if not self.coresys.os.available or self.coresys.os.version < "15.0":
raise HTTPNotFound()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the status codes, this is the only one that makes sense. That being said, we can provide a better explanation then this so I think we should. Something like telling them this API requires the system be HAOS with version >= 15.0 . And perhaps log this as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point. I also kind of forgot about our APINotFound here 🙈

Comment on lines 74 to 75
vol.Optional(ATTR_SWAP_SIZE): vol.Coerce(str),
vol.Optional(ATTR_SWAPPINESS): vol.Coerce(int),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems very open-ended, is it actually this open-ended? Can we provide any further validation on the string? Maybe vol.Match([1-9][0-9]M)? I'm guessing based on the test cases. Although actually if M is the only allowed unit we should probably just require a positive integer instead and add the M for them.

Similar question on swappiness. Is there a valid range of values? If its just a positive number then we can do vol.All(int, vol.Range(min=0)) or min=1 if 0 is invalid.

Additionally we don't want coerce for str and int. Those data types can be expressed in JSON so we should require that the JSON has a str or an int, not something that can be coerced into a str or int

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll improve the validations. Swappiness can be only 0-200, that's what Linux accepts. For swap size it's actually quite permissive: https://github.com/home-assistant/operating-system/blob/15.0/buildroot-external/rootfs-overlay/usr/libexec/haos-swapfile#L4-L14

I'll add a regexp that matches what's defined there.

@home-assistant
Copy link

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

@home-assistant home-assistant bot marked this pull request as draft March 20, 2025 20:37
@mdegat01 mdegat01 added missing-documentation Added to pull requests that needs a docs, but none is linked need-cli Added to pull requests that need cli changes but none is linked need-client-library Added to pull requests that need client library changes but none is linked labels Mar 20, 2025
@mdegat01
Copy link
Contributor

@sairon btw this outside diff range comment by coderabbit here is right:

Actionable comments posted: 3
🔭 Outside diff range comments (1)

supervisor/dbus/agent/init.py (1)> 97-99: ⚠️ Potential issue

Missing swap in the 'all' property.
The all property returns a list of all managed DBUS interfaces, but it doesn't include the newly added self._swap. This could cause issues with methods that rely on this list being complete, such as the connect and shutdown methods.

@property
def all(self) -> list[DBusInterface]:
    """Return all managed dbus interfaces."""
-    return [self.apparmor, self.board, self.cgroup, self.datadisk, self.system]
+    return [self.apparmor, self.board, self.cgroup, self.datadisk, self.system, self.swap]

self.swap needs to be added to the list returned by all in that object or else the dbus object won't be loaded at startup here:

errors = await asyncio.gather(
*[dbus.connect(bus) for dbus in self.all], return_exceptions=True
)

sairon and others added 4 commits March 26, 2025 17:56
Add HTTP API for swap size and swappiness to /os/config/swap. Individual
options can be set in JSON and are calling the DBus API added in OS
Agent 1.7.x, available since OS 15.0. Check for presence of OS of the
required version and return 404 if the criteria are not met.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- Improve swap options validation
- Add swap to the 'all' property of dbus agent
- Use APINotFound with reason instead of HTTPNotFound
- Reorder API routes
@sairon sairon requested a review from mdegat01 March 26, 2025 16:58
@sairon sairon marked this pull request as ready for review March 26, 2025 16:58
@sairon
Copy link
Member Author

sairon commented Mar 26, 2025

Thanks for the comments, I've addressed them and rebased the PR.

@agners agners merged commit 0a684bd into main Mar 27, 2025
22 checks passed
@agners agners deleted the add-swap-api branch March 27, 2025 16:53
@github-actions github-actions bot locked and limited conversation to collaborators Mar 29, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla-signed missing-documentation Added to pull requests that needs a docs, but none is linked need-cli Added to pull requests that need cli changes but none is linked need-client-library Added to pull requests that need client library changes but none is linked new-feature A new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants