Skip to content

fix: vms now can detect starting of libvirt and start local hypervisor#1356

Merged
elibosley merged 3 commits intomainfrom
fix/vms-watcher-for-pid
Apr 14, 2025
Merged

fix: vms now can detect starting of libvirt and start local hypervisor#1356
elibosley merged 3 commits intomainfrom
fix/vms-watcher-for-pid

Conversation

@elibosley
Copy link
Member

@elibosley elibosley commented Apr 14, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced virtual machine services now benefit from improved initialization, dynamic monitoring, and cleaner shutdown, ensuring a smoother operational experience.
    • Strengthened input validation for array state changes helps users avoid improper commands and enhances overall reliability.
  • Bug Fixes

    • Refined state and disk management logic prevents redundant operations and incorrect transitions, leading to a more stable system.
  • Refactor

    • Streamlined status reporting delivers clearer and more accurate array state information for end-users.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 14, 2025

Walkthrough

This pull request removes deprecated fields and enums in the GraphQL schema and updates related models by adding stricter validations. It refactors the array service to use asynchronous methods for state checking and introduces a new internal enum. The VmsService now implements both initialization and cleanup for file system watching of the PID file. Additionally, redundant utility functions and index files are removed, and the ArrayService test suite is reorganized to enhance error handling and clarity.

Changes

File(s) Change Summary
api/generated-schema.graphql
api/src/unraid-api/graph/resolvers/array/array.model.ts
Removed previousState and pendingState fields from UnraidArray and deleted the ArrayPendingState enum. Added @IsEnum(ArrayStateInputState) to the desiredState field in ArrayStateInput.
api/src/unraid-api/graph/resolvers/vms/vms.service.ts Updated VmsService to implement the OnModuleDestroy lifecycle, introduced a new FSWatcher property, and added methods for hypervisor initialization and PID file watching.
api/src/core/utils/array/array-is-running.ts
api/src/core/utils/array/index.ts
api/src/core/utils/index.ts
Deleted the arrayIsRunning utility function and removed related re-export files from the module index.
api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
api/src/unraid-api/graph/resolvers/array/array.service.ts
Refactored the ArrayService test suite with improved error handling, renamed methods, updated mocks, and converted key service methods to asynchronous flows with a new internal enum for pending states.

Sequence Diagram(s)

sequenceDiagram
    participant VS as VmsService
    participant FW as FileWatcher
    participant H as Hypervisor

    VS->>VS: onModuleInit()
    VS->>FW: attemptHypervisorInitializationAndWatch()
    FW->>H: initializeHypervisor()
    note over VS,FW: Watcher monitors PID file events
    FW->>VS: PID file added/removed event
    alt PID file added
        VS->>H: initializeHypervisor()
    else PID file removed
        VS->>H: close hypervisor connection
    end
    VS->>FW: onModuleDestroy() triggers watcher close
    VS->>H: onModuleDestroy() cleans up hypervisor connection
Loading
sequenceDiagram
    participant C as Client
    participant AS as ArrayService
    participant S as State Store

    C->>AS: updateArrayState(newState)
    AS->>AS: async arrayIsRunning()
    AS->>S: get current state
    S-->>AS: return state
    alt Array is running
        AS->>C: throw BadRequestException
    else Array is not running
        AS->>AS: update newPendingState (STARTING/STOPPING)
        AS->>C: return updated state
    end
Loading

Suggested reviewers

  • pujitm
  • zackspear
  • mdatelle

Poem

In lines of code a change does gleam,
Deprecated fields now fade like a dream.
Watchers awake on the file system's call,
Async flows now guide one and all.
Tests refined, errors caught in sight,
CodeRabbit’s art sparkles in byte-light!
🚀✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 519f1c1 and 9a63897.

📒 Files selected for processing (8)
  • api/generated-schema.graphql (0 hunks)
  • api/src/core/utils/array/array-is-running.ts (0 hunks)
  • api/src/core/utils/array/index.ts (0 hunks)
  • api/src/core/utils/index.ts (0 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.model.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.service.ts (7 hunks)
  • api/src/unraid-api/graph/resolvers/vms/vms.service.ts (2 hunks)
💤 Files with no reviewable changes (4)
  • api/src/core/utils/index.ts
  • api/src/core/utils/array/index.ts
  • api/generated-schema.graphql
  • api/src/core/utils/array/array-is-running.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • api/src/unraid-api/graph/resolvers/array/array.model.ts
  • api/src/unraid-api/graph/resolvers/array/array.service.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
api/src/unraid-api/graph/resolvers/vms/vms.service.ts (4)
api/src/unraid-api/graph/resolvers/array/array.service.ts (1)
  • Injectable (23-164)
api/src/unraid-api/auth/auth.interceptor.ts (1)
  • Injectable (12-25)
api/src/unraid-api/auth/api-key.service.ts (1)
  • Injectable (27-377)
api/src/store/index.ts (1)
  • getters (18-29)
api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (2)
web/composables/gql/graphql.ts (3)
  • UnraidArray (1350-1369)
  • ArrayStateInput (252-255)
  • ArrayDiskInput (159-164)
api/src/core/utils/clients/emcmd.ts (1)
  • emcmd (12-41)
🔇 Additional comments (16)
api/src/unraid-api/graph/resolvers/vms/vms.service.ts (10)

1-1: Implementation of OnModuleDestroy matches well with the added functionality

The addition of OnModuleDestroy interface is appropriate for implementing the lifecycle cleanup for the file watcher and hypervisor connection.

Also applies to: 14-14


7-7: Good use of FSWatcher and proper type definition

Adding the chokidar watcher with appropriate type definition enhances code safety and provides proper handling of file system events.

Also applies to: 18-20


22-26: Improved constructor with better error handling

Good improvement to store the PID path as a class property with a fallback value. The debug logging adds valuable information for troubleshooting.


28-39: Clean and consistent implementation of isLibvirtRunning

The method now directly uses the class property instead of accessing it via getters, which is more maintainable and consistent.


41-44: Clean onModuleInit implementation

The updated onModuleInit method with better logging and proper initialization through the new attemptHypervisorInitializationAndWatch method aligns well with the PR objective.


46-58: Robust implementation of onModuleDestroy

The implementation properly cleans up resources by closing both the file watcher and hypervisor connection. Good error handling ensures that errors during cleanup are caught and logged.


60-73: Well-structured initialization with fallback handling

The attemptHypervisorInitializationAndWatch method properly attempts hypervisor initialization and sets up a watcher even if initialization fails, allowing for recovery when libvirt becomes available.


75-128: Comprehensive file watcher implementation

The setupWatcher method efficiently:

  1. Closes any existing watcher before creating a new one
  2. Sets up watchers with appropriate options for monitoring the PID file
  3. Handles file addition events to reconnect to the hypervisor
  4. Handles file removal events to update service state and close connections
  5. Provides detailed error logging

This implementation directly addresses the PR objective of detecting when libvirt starts and initializing the hypervisor.


130-161: Optimized hypervisor initialization

The addition of the early return based on hypervisor existence and availability flag prevents unnecessary reconnection attempts, improving efficiency.


371-380: Enhanced error handling in getDomains

The updated error handling provides more specific logging for connection issues versus other errors, which will help with debugging and troubleshooting.

api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (6)

1-91: Well-structured test setup with improved mocking

The test file has been significantly improved with:

  1. More specific type definitions (UnraidArray instead of any)
  2. Better organization of mock setup
  3. Proper reset of mocks before each test
  4. Complete mock implementations for all required dependencies

These changes provide a more robust foundation for testing the ArrayService.


97-104: Clear and focused test for getArrayData

The test properly verifies that getArrayData calls the utility function with the correct parameters and returns the expected result.


106-152: Comprehensive testing of updateArrayState

The tests cover all important scenarios:

  1. Starting a stopped array
  2. Stopping a started array
  3. Error handling for invalid state transitions

The expectations are clear and verify both the returned values and the correct interaction with mocked dependencies.


154-172: Proper testing of addDiskToArray with appropriate error checks

The tests verify both the success case and the error case when the array is running, ensuring the function behaves correctly in all scenarios.


174-192: Thorough testing of removeDiskFromArray

Similar to addDiskToArray, these tests properly verify both success and failure cases with appropriate assertions.


194-258: Complete test coverage for disk operations

The tests for mountArrayDisk, unmountArrayDisk, and clearArrayDiskStatistics are well-structured and verify:

  1. Successful operations when the array is in the correct state
  2. Error handling when operations are attempted in an invalid state
  3. Correct parameters passed to the underlying commands

This ensures all disk operation functions work correctly and handle errors appropriately.


🪧 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 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 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: 0

🧹 Nitpick comments (2)
api/src/unraid-api/graph/resolvers/vms/vms.service.ts (2)

75-132: Watcher setup is thorough.
File events are clearly handled, though consider potential load if the file changes frequently.


376-384: Enhanced error differentiation is helpful.
Logging a specific message for connection failures vs. other errors can improve troubleshooting. Consider custom error types for further clarity.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2345732 and afac350.

📒 Files selected for processing (3)
  • api/generated-schema.graphql (1 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.model.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/vms/vms.service.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
api/src/unraid-api/graph/resolvers/array/array.model.ts (1)
web/composables/gql/graphql.ts (1)
  • ArrayStateInput (252-255)
api/src/unraid-api/graph/resolvers/vms/vms.service.ts (1)
api/src/store/index.ts (1)
  • getters (18-29)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Build Web App
  • GitHub Check: Test API
  • GitHub Check: Build API
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (9)
api/generated-schema.graphql (1)

1424-1424:

Details

✅ Verification successful

Ensure a proper resolver for this new field.
A resolver must be implemented or updated so clients can actually query the health field.


🏁 Script executed:

#!/bin/bash
# Checking where the 'health' field is handled in resolvers
rg -A 5 'health'

Length of output: 36640


Health Field Resolver Confirmed

The new health: String! field in api/generated-schema.graphql is properly backed by resolvers. We found resolver implementations in both:

  • packages/unraid-api-plugin-health/index.ts – returns 'OK'
  • packages/unraid-api-plugin-connect/index.ts – returns "I am healthy!"

No further changes are required.

api/src/unraid-api/graph/resolvers/array/array.model.ts (2)

3-4: Import statement looks good.
This addition properly includes the class-validator dependency for enum validation with no issues.


185-190: Enum validation on desiredState is beneficial.
This guarantees only valid states are accepted, avoiding invalid transitions.

api/src/unraid-api/graph/resolvers/vms/vms.service.ts (6)

1-1: Implementation of OnModuleDestroy is a great addition.
Resource cleanup on module destruction helps prevent leaks.

Also applies to: 14-14


7-7: Chokidar import is appropriate.
Using chokidar is a reliable way to watch for file changes across platforms.


43-44: Graceful teardown in onModuleDestroy is well-handled.
Ensuring the watcher and hypervisor connections are closed avoids dangling resources.

Also applies to: 46-58


60-60: Fallback connection logic is good.
Attempting hypervisor init and then setting up the watcher ensures robust startup behavior, even if the initial connection fails.

Also applies to: 67-67, 69-71, 73-73


135-138: Hypervisor re-initialization check is effective.
The logic avoids redundant connections by respecting isVmsAvailable.

Also applies to: 140-140, 145-145, 148-148


18-20:

Details

✅ Verification successful

Validate fallback path usage for pidPath.
If getters.paths()?.['libvirt-pid'] is undefined, confirm the fallback /var/run/libvirt/libvirtd.pid is correct for target environments.

Also applies to: 24-25, 34-34


🏁 Script executed:

#!/bin/bash
# Verify references to libvirtd.pid fallback
rg -A3 'libvirt-pid'

Length of output: 858


Validated pidPath Fallback Configuration

The fallback path /var/run/libvirt/libvirtd.pid is consistently used and correctly configured:

  • In api/src/unraid-api/graph/resolvers/vms/vms.service.ts, the fallback is applied via the nullish coalescing operator.
  • In api/src/store/modules/paths.ts, the constant value is defined as expected.

No further action is required.

@elibosley elibosley force-pushed the fix/vms-watcher-for-pid branch from afac350 to 851ccb7 Compare April 14, 2025 15:46
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: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between afac350 and 851ccb7.

📒 Files selected for processing (3)
  • api/generated-schema.graphql (1 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.model.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/vms/vms.service.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • api/generated-schema.graphql
  • api/src/unraid-api/graph/resolvers/array/array.model.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
api/src/unraid-api/graph/resolvers/vms/vms.service.ts (1)
api/src/store/index.ts (1)
  • getters (18-29)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Build Web App
  • GitHub Check: Build API
  • GitHub Check: Test API
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (13)
api/src/unraid-api/graph/resolvers/vms/vms.service.ts (13)

1-1: Excellent implementation of the OnModuleDestroy lifecycle hook

The addition of the OnModuleDestroy interface and required watcher property provides proper lifecycle management for the VmsService class, ensuring resources are cleaned up when the module is destroyed.

Also applies to: 14-14, 18-18, 20-20


7-7: Good addition of file system watching capabilities

Adding the chokidar library for file system watching is appropriate for monitoring the libvirt PID file changes.


24-25: Appropriate path initialization and logging

Good practice to initialize the pidPath in the constructor and log its value for debugging purposes.


34-34: Improved path reference

Using the class property directly rather than accessing through getters.paths() each time is more efficient.


42-44: Clear initialization sequence

The modified onModuleInit method provides better logging and delegates to the new specialized initialization method.


46-58: Well-implemented resource cleanup

The onModuleDestroy method properly handles the cleanup of resources, with good error handling for the hypervisor connection close operation.


60-73: Good separation of concerns

This method effectively separates the hypervisor initialization and watcher setup, with appropriate error handling.


92-109: Good PID file detection handling

The 'add' event handler correctly attempts to initialize the hypervisor when the PID file is detected, with appropriate error handling.


110-126: Robust PID file removal handling

The 'unlink' event handler properly handles the case when the PID file is removed, indicating that the hypervisor has stopped.


127-131: Comprehensive error handling

The error event handler ensures that any watcher errors are properly logged.


135-138: Efficient hypervisor initialization check

Good practice to check if the hypervisor is already active before attempting to initialize it again.


140-149: Improved hypervisor creation logic

The refined hypervisor creation logic with better logging improves the code's readability and maintainability.


376-384: Enhanced error differentiation

The improved error handling in getDomains method differentiates between connection issues and other errors, providing more specific error messages.

@elibosley
Copy link
Member Author

elibosley commented Apr 14, 2025

Tested this on my server:


[09:17:48.647] WARN: Libvirt PID file removed from /var/run/libvirt/libvirtd.pid. Hypervisor likely stopped. {"logger":"api","context":"VmsService"}
[09:18:01.577] INFO: Libvirt PID file detected at /var/run/libvirt/libvirtd.pid. Attempting connection... {"logger":"api","context":"VmsService"}
[09:18:01.578] INFO: Hypervisor connection established successfully after PID file detection. {"logger":"api","context":"VmsService"}

@elibosley elibosley force-pushed the fix/vms-watcher-for-pid branch from 519f1c1 to 9a63897 Compare April 14, 2025 17:30
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 (5)
api/src/unraid-api/graph/resolvers/array/array.model.ts (1)

176-182: Consider test coverage for the new ArrayStateInput class.
Adding tests to verify the enum validation behavior would help you catch unexpected input values and guarantee that the intended states are enforced at runtime.

api/src/unraid-api/graph/resolvers/array/array.service.ts (2)

37-41: Question the need for a separate getArrayState method.
Since arrayIsRunning already fetches and checks the state, consider whether you require this function’s additional abstraction to reduce duplication.


51-51: Refine or clarify the exception message.
Including the pending state in the error is helpful, but consider clarifying it so users clearly understand which state is currently preventing updates vs. which state they want.

api/src/unraid-api/graph/resolvers/vms/vms.service.ts (1)

60-73: Graceful fallback if hypervisor initialization fails.
After the first attempt fails, you still set up the watcher. Consider whether a small retry loop might reduce logs or shorten downtime if libvirt starts a bit late.

api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (1)

45-52: Well-structured test setup

The beforeEach block properly resets all mocks, initializes them with appropriate return values, and sets up the test environment. The mock data structure aligns with the UnraidArray type.

However, line 89 contains a comment about mocking state if needed, but no actual state is defined.

 mockGetState.mockReturnValue({
-    /* mock state if needed by getArrayDataUtil */
+    // Return mock state structure needed by getArrayDataUtil
+    array: {
+        // Add relevant state properties here
+    }
 });

Also applies to: 60-61, 81-81, 86-90

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 851ccb7 and 519f1c1.

📒 Files selected for processing (10)
  • api/dev/Unraid.net/myservers.cfg (1 hunks)
  • api/generated-schema.graphql (1 hunks)
  • api/src/core/utils/array/array-is-running.ts (0 hunks)
  • api/src/core/utils/array/index.ts (0 hunks)
  • api/src/core/utils/index.ts (0 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.model.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.resolver.ts (0 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.service.ts (7 hunks)
  • api/src/unraid-api/graph/resolvers/vms/vms.service.ts (2 hunks)
💤 Files with no reviewable changes (4)
  • api/src/core/utils/array/array-is-running.ts
  • api/src/core/utils/index.ts
  • api/src/core/utils/array/index.ts
  • api/src/unraid-api/graph/resolvers/array/array.resolver.ts
✅ Files skipped from review due to trivial changes (1)
  • api/dev/Unraid.net/myservers.cfg
🚧 Files skipped from review as they are similar to previous changes (1)
  • api/generated-schema.graphql
🧰 Additional context used
🧬 Code Graph Analysis (3)
api/src/unraid-api/graph/resolvers/array/array.model.ts (1)
web/composables/gql/graphql.ts (1)
  • ArrayStateInput (252-255)
api/src/unraid-api/graph/resolvers/vms/vms.service.ts (2)
api/src/unraid-api/auth/api-key.service.ts (1)
  • Injectable (27-377)
api/src/store/index.ts (1)
  • getters (18-29)
api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (2)
web/composables/gql/graphql.ts (3)
  • UnraidArray (1350-1369)
  • ArrayStateInput (252-255)
  • ArrayDiskInput (159-164)
api/src/core/utils/clients/emcmd.ts (1)
  • emcmd (12-41)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (22)
api/src/unraid-api/graph/resolvers/array/array.model.ts (1)

3-4: Use of IsEnum appears appropriate.
This import correctly enables validation for the enum field. Ensure that class-validator is included in your runtime dependencies to avoid runtime errors.

api/src/unraid-api/graph/resolvers/array/array.service.ts (7)

18-21: Enum ArrayPendingState integration looks consistent.
No specific issues here. This addition cleanly captures the transitional states.


31-35: Asynchronous arrayIsRunning is a neat improvement.
Fetching the array state from the store asynchronously helps avoid potential blocking. Good move.


43-46: Ensure getArrayData handles errors consistently.
Switching to an async method seems appropriate. If getArrayDataUtil rejects, ensure you handle it (or let it bubble up) in a predictable manner.


54-55: Local state determination is streamlined.
Preparing startState by referencing isRunning is a clean approach. Ensure test coverage includes both scenarios to confirm correct branching.


62-66: Early exit for same-state requests looks good.
Blocking redundant start/stop requests protects from unintended operations. Nicely done.


71-71: Setting pendingState prior to the operation is wise.
This ensures concurrency conflicts are minimized. Remain mindful of parallel requests that might overwrite this state unexpectedly.


90-90: Consistency in disallowing disk operations while running.
Throwing ArrayRunningError if the array is running keeps your domain logic coherent. Just verify that this is indeed the intended restriction in all these methods.

Also applies to: 107-107, 124-124, 138-138, 152-152

api/src/unraid-api/graph/resolvers/vms/vms.service.ts (7)

1-1: Adoption of OnModuleDestroy, FSWatcher, and storing pidPath is well-structured.
The fallback default path for libvirt-pid ensures the service remains robust even if not explicitly configured.

Also applies to: 7-7, 14-14, 18-18, 20-20, 24-25


34-34: Ensuring read access to the PID file.
This check makes sense for confirming libvirt is running. Handling partial permission issues may be overkill, so no immediate concerns.


42-44: Calling attemptHypervisorInitializationAndWatch on module init.
A single entry point for initialization plus watch setup is tidy. Relying on subsequent watch triggers if the initial connect fails is a sensible fallback.


46-58: Thorough cleanup in onModuleDestroy.
You properly close the watcher and hypervisor, safely handling potential errors. This ensures resources are released.


75-128: setupWatcher elegantly handles PID addition and removal events.
You correctly toggle isVmsAvailable and attempt to reconnect when needed. The approach looks solid for ephemeral service restarts.


131-161: initializeHypervisor method is well-structured.
You confirm the PID file presence, create a hypervisor, and attempt to connect. This flow, combined with error-handling, is straightforward.


372-380: Improved error handling for domain lookups.
Logging distinct connection issues vs. general failures simplifies debugging. Good detail here.

api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (7)

2-2: Import changes look well-structured

The added imports introduce necessary error types (BadRequestException, ArrayRunningError) and properly rename the getArrayData import to getArrayDataUtil to avoid naming conflicts with the service method. The UnraidArray type is also correctly imported to provide proper typing for the test data.

Also applies to: 7-8, 15-15


23-25: Good mock setup with proper typing

The test file properly mocks all external dependencies including the array data utility and store functions. The variable declarations use proper TypeScript return types instead of any, which improves type safety throughout the tests.

Also applies to: 31-33, 38-42


97-104: Good test for getArrayData method

This test properly verifies that the service method calls the utility function with the right arguments and returns its result.


106-152: Comprehensive tests for updateArrayState method

The tests cover all important scenarios: starting a stopped array, stopping a started array, and attempting invalid state transitions. The error handling tests verify both the exception type and that no commands are executed.


154-172: Complete tests for addDiskToArray

Tests cover both the success case when the array is stopped and the error case when trying to add a disk to a running array. The verification of the emcmd call parameters ensures the command is constructed correctly.


174-192: Good test coverage for removeDiskFromArray

Similar to the add disk tests, this section correctly verifies both success and failure scenarios with appropriate assertions.


194-214: Well-structured tests for disk operations

The mountArrayDisk, unmountArrayDisk, and clearArrayDiskStatistics tests all follow a consistent pattern of testing both success and failure cases. Each test verifies the correct command parameters and error handling behavior.

Also applies to: 216-236, 238-258

@github-actions
Copy link
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1356/dynamix.unraid.net.plg

@elibosley elibosley linked an issue Apr 14, 2025 that may be closed by this pull request
@elibosley elibosley mentioned this pull request Apr 14, 2025
@elibosley elibosley merged commit ad0f4c8 into main Apr 14, 2025
9 checks passed
@elibosley elibosley deleted the fix/vms-watcher-for-pid branch April 14, 2025 18:59
elibosley pushed a commit that referenced this pull request Apr 24, 2025
🤖 I have created a release *beep* *boop*
---


## [4.7.0](v4.6.6...v4.7.0)
(2025-04-24)


### Features

* add basic docker network listing
([#1317](#1317))
([c4fdff8](c4fdff8))
* add permission documentation by using a custom decorator
([#1355](#1355))
([45ecab6](45ecab6))
* basic vm controls ([#1293](#1293))
([bc3ca92](bc3ca92))
* code first graphql
([#1347](#1347))
([f5724ab](f5724ab))


### Bug Fixes

* container names always null
([#1335](#1335))
([8a5b238](8a5b238))
* **deps:** update all non-major dependencies
([#1337](#1337))
([2345732](2345732))
* hide reboot notice for patch releases
([#1341](#1341))
([4b57439](4b57439))
* move docker mutations to the mutations resolver
([#1333](#1333))
([1bbe7d2](1bbe7d2))
* PR build issue
([457d338](457d338))
* remove some unused fields from the report object
([#1342](#1342))
([cd323ac](cd323ac))
* sso unreliable if API outputs more than raw json
([#1353](#1353))
([e65775f](e65775f))
* vms now can detect starting of libvirt and start local hypervisor
([#1356](#1356))
([ad0f4c8](ad0f4c8))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mutation Array

2 participants