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

feat(backingimage): support spdk backing image #728

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ChanYiLin
Copy link
Contributor

ref: longhorn/longhorn#6341

  • Add BackingImage Proxy API to BackingImage SPDK Server API

@ChanYiLin ChanYiLin self-assigned this Nov 29, 2024
Copy link

coderabbitai bot commented Nov 29, 2024

Walkthrough

The changes introduce a new API for managing backing images, enhancing the existing structures and methods across multiple files. A new BackingImage struct and related functions are defined in backing_image.go, enabling conversion and management of backing images. The ReplicaCreateRequest struct in instance.go is updated to include a BackingImageName field. New methods for creating, deleting, retrieving, and listing backing images are added in proxy_backing_image.go and backing_image.go. Additionally, version management for the backing image service is implemented in version.go, ensuring compatibility with existing services.

Changes

File Path Change Summary
pkg/api/backing_image.go Added BackingImage, BackingImageStatus, and BackingImageStream structs; added functions for converting RPC responses and managing streams.
pkg/client/instance.go Added BackingImageName field to ReplicaCreateRequest; updated InstanceCreate method to include this field.
pkg/client/proxy_backing_image.go Introduced ProxyClient struct with methods for creating, deleting, retrieving, listing, and watching backing images via gRPC.
pkg/instance/instance.go Updated InstanceCreate method signature to include BackingImageName for replica creation.
pkg/meta/version.go Added version management for backing image service with constants and a struct for version output; introduced a version retrieval function.
pkg/proxy/backing_image.go Added Proxy struct with methods for managing SPDK backing images; included error handling and logging.
pkg/proxy/proxy.go Enhanced Proxy struct with spdkServiceAddress and spdkLocalClient; updated NewProxy function to initialize these fields.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ProxyClient
    participant BackingImageService

    Client->>ProxyClient: SPDKBackingImageCreate(name, UUID, checksum, size)
    ProxyClient->>BackingImageService: CreateBackingImageRequest
    BackingImageService-->>ProxyClient: CreateBackingImageResponse
    ProxyClient-->>Client: BackingImageResponse
Loading
sequenceDiagram
    participant Client
    participant ProxyClient
    participant BackingImageService

    Client->>ProxyClient: SPDKBackingImageList()
    ProxyClient->>BackingImageService: ListBackingImagesRequest
    BackingImageService-->>ProxyClient: ListBackingImagesResponse
    ProxyClient-->>Client: BackingImageListResponse
Loading

Warning

Rate limit exceeded

@ChanYiLin has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 10 minutes and 5 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between cca5967 and 18ed15a.

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 golangci-lint (1.62.2)

level=warning msg="[runner] Can't run linter goanalysis_metalinter: buildir: failed to load package qcow: could not load export data: no export data for "github.com/longhorn/longhorn-engine/pkg/qcow""
level=error msg="Running error: can't run linter goanalysis_metalinter\nbuildir: failed to load package qcow: could not load export data: no export data for "github.com/longhorn/longhorn-engine/pkg/qcow""


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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 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.

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.

ref: longhorn/longhorn 6341

Signed-off-by: Jack Lin <[email protected]>
Copy link

@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: 8

🧹 Outside diff range and nitpick comments (7)
pkg/api/backing_image.go (1)

8-16: Add documentation and field validation.

The struct looks well-designed, but could benefit from:

  1. GoDoc comments explaining the purpose of the struct and each field
  2. Validation logic for required fields (Name, BackingImageUUID, Size)

Consider adding documentation and validation like this:

+// BackingImage represents a SPDK backing image with its properties and current status
 type BackingImage struct {
+       // Name is the unique identifier of the backing image
        Name             string `json:"name"`
+       // BackingImageUUID is the UUID assigned to this backing image
        BackingImageUUID string `json:"backing_image_uuid"`
        // ... (add comments for other fields)
 }

+// Validate ensures all required fields are present
+func (bi *BackingImage) Validate() error {
+       if bi.Name == "" {
+               return fmt.Errorf("backing image name is required")
+       }
+       if bi.BackingImageUUID == "" {
+               return fmt.Errorf("backing image UUID is required")
+       }
+       if bi.Size == 0 {
+               return fmt.Errorf("backing image size must be greater than 0")
+       }
+       return nil
+}
pkg/meta/version.go (1)

83-92: Consider future refactoring to reduce duplication.

The version management pattern (Version, GitCommit, BuildDate) is duplicated across multiple structs (VersionOutput, DiskServiceVersionOutput, BackingImageServiceVersionOutput). Consider introducing a common base struct in a future refactoring to follow the DRY principle.

Example approach:

type BaseVersionInfo struct {
    Version   string `json:"version"`
    GitCommit string `json:"gitCommit"`
    BuildDate string `json:"buildDate"`
}

type BackingImageServiceVersionOutput struct {
    BaseVersionInfo
    InstanceManagerBackingImageServiceAPIVersion    int `json:"instanceManagerBackingImageServiceAPIVersion"`
    InstanceManagerBackingImageServiceAPIMinVersion int `json:"instanceManagerBackingImageServiceAPIMinVersion"`
}
pkg/proxy/proxy.go (2)

64-66: Consider adding cleanup for SPDK client

While the field additions are appropriate, consider implementing a cleanup method for the spdkLocalClient to ensure proper resource release. This could be done by extending the existing context cancellation handling in startMonitoring().

 func (p *Proxy) startMonitoring() {
 	<-p.ctx.Done()
+	if p.spdkLocalClient != nil {
+		if err := p.spdkLocalClient.Close(); err != nil {
+			logrus.WithError(err).Error("Failed to close SPDK client")
+		}
+	}
 	logrus.Infof("%s: stopped monitoring due to the context done", types.ProxyGRPCService)
 }

Line range hint 128-144: Fix error handling in getSPDKClientFromAddress

The error check after net.JoinHostPort is unnecessary as this function only returns an error when given invalid input, which isn't possible here since we've already validated the host through SplitHostPort. Additionally, the error isn't being used in the condition.

 func getSPDKClientFromAddress(address string) (*spdkclient.SPDKClient, error) {
 	host, _, err := net.SplitHostPort(address)
 	if err != nil {
 		return nil, err
 	}

 	spdkServiceAddress := net.JoinHostPort(host, strconv.Itoa(types.InstanceManagerSpdkServiceDefaultPort))
-	if err != nil {
-		return nil, err
-	}

 	return spdkclient.NewSPDKClient(spdkServiceAddress)
 }
pkg/client/instance.go (1)

98-101: Add documentation and validation for BackingImageName field

While the field addition follows the struct's pattern, consider:

  1. Adding field documentation to explain its purpose and requirements
  2. Adding validation logic in the InstanceCreate method to ensure BackingImageName meets any format/length requirements when specified
 type ReplicaCreateRequest struct {
+        // DiskName is the name of the disk where the replica will be created
        DiskName         string
+        // DiskUUID is the unique identifier of the disk
        DiskUUID         string
+        // ExposeRequired indicates if the replica needs to be exposed
        ExposeRequired   bool
+        // BackingImageName specifies the name of the SPDK backing image to use
        BackingImageName string
 }
pkg/client/proxy_backing_image.go (1)

33-34: Ensure consistent error wrapping for improved error context

In the methods SPDKBackingImageCreate, SPDKBackingImageDelete, and SPDKBackingImageGet, errors are returned directly without additional context. However, in SPDKBackingImageList and SPDKBackingImageWatch, errors are wrapped using errors.Wrap. For consistency and better error tracing, consider wrapping errors in all methods.

Apply this diff to wrap errors consistently:

@@ -33,7 +33,7 @@
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrap(err, "failed to create backing image")
 	}

@@ -52,7 +52,7 @@
-	return err
+	return errors.Wrap(err, "failed to delete backing image")

@@ -69,7 +69,7 @@
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrap(err, "failed to get backing image")
 	}

Also applies to: 52-52, 69-70

pkg/proxy/backing_image.go (1)

38-38: Correct the casing of 'SPDK' in log messages

The term "SPDK" should be fully capitalized in log messages. Currently, it's written as "SPDk".

Apply the following diff to correct the log messages:

- log.Info("Backing Image Server: Creating SPDk Backing Image")
+ log.Info("Backing Image Server: Creating SPDK Backing Image")

- log.Info("Backing Image Server: Deleting SPDk Backing Image")
+ log.Info("Backing Image Server: Deleting SPDK Backing Image")

- log.Info("Backing Image Server: Get SPDk Backing Image")
+ log.Info("Backing Image Server: Getting SPDK Backing Image")

- logrus.Info("Backing Image Server: List SPDk Backing Image")
+ logrus.Info("Backing Image Server: Listing SPDK Backing Images")

Also applies to: 56-56, 68-68, 80-80

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between cca5967 and 18ed15a.

⛔ Files ignored due to path filters (192)
  • go.mod is excluded by !go.mod
  • go.sum is excluded by !**/*.sum, !go.sum
  • vendor/github.com/bits-and-blooms/bitset/README.md is excluded by !vendor/**
  • vendor/github.com/bits-and-blooms/bitset/bitset.go is excluded by !vendor/**
  • vendor/github.com/bits-and-blooms/bitset/leading_zeros_18.go is excluded by !vendor/**
  • vendor/github.com/bits-and-blooms/bitset/leading_zeros_19.go is excluded by !vendor/**
  • vendor/github.com/bits-and-blooms/bitset/select.go is excluded by !vendor/**
  • vendor/github.com/coreos/go-systemd/v22/LICENSE is excluded by !vendor/**
  • vendor/github.com/coreos/go-systemd/v22/NOTICE is excluded by !vendor/**
  • vendor/github.com/coreos/go-systemd/v22/dbus/dbus.go is excluded by !vendor/**
  • vendor/github.com/coreos/go-systemd/v22/dbus/methods.go is excluded by !vendor/**
  • vendor/github.com/coreos/go-systemd/v22/dbus/properties.go is excluded by !vendor/**
  • vendor/github.com/coreos/go-systemd/v22/dbus/set.go is excluded by !vendor/**
  • vendor/github.com/coreos/go-systemd/v22/dbus/subscription.go is excluded by !vendor/**
  • vendor/github.com/coreos/go-systemd/v22/dbus/subscription_set.go is excluded by !vendor/**
  • vendor/github.com/gammazero/deque/README.md is excluded by !vendor/**
  • vendor/github.com/gammazero/deque/deque.go is excluded by !vendor/**
  • vendor/github.com/gammazero/deque/doc.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/CONTRIBUTING.md is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/LICENSE is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/MAINTAINERS is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/README.md is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/auth.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/auth_anonymous.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/auth_external.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/auth_sha1.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/call.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/conn.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/conn_darwin.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/conn_other.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/conn_unix.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/conn_windows.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/dbus.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/decoder.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/default_handler.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/doc.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/encoder.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/escape.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/export.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/homedir.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/match.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/message.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/object.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/sequence.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/sequential_handler.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/server_interfaces.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/sig.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_darwin.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_generic.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_tcp.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_unix.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_unixcred_dragonfly.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_unixcred_freebsd.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_unixcred_linux.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_unixcred_openbsd.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/transport_zos.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/variant.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/variant_lexer.go is excluded by !vendor/**
  • vendor/github.com/godbus/dbus/v5/variant_parser.go is excluded by !vendor/**
  • vendor/github.com/longhorn/go-spdk-helper/pkg/spdk/client/basic.go is excluded by !vendor/**
  • vendor/github.com/longhorn/go-spdk-helper/pkg/spdk/types/lvol.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/api/types.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/client/client.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/spdk/backing_image.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/spdk/backup.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/spdk/engine.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/spdk/replica.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/spdk/server.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/spdk/types.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/spdk/util.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/types/types.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/util/http_handler.go is excluded by !vendor/**
  • vendor/github.com/longhorn/longhorn-spdk-engine/pkg/util/util.go is excluded by !vendor/**
  • vendor/github.com/longhorn/types/pkg/generated/imrpc/instance.pb.go is excluded by !**/*.pb.go, !**/generated/**, !vendor/**
  • vendor/github.com/longhorn/types/pkg/generated/imrpc/proxy.pb.go is excluded by !**/*.pb.go, !**/generated/**, !vendor/**
  • vendor/github.com/longhorn/types/pkg/generated/imrpc/proxy_grpc.pb.go is excluded by !**/*.pb.go, !**/generated/**, !vendor/**
  • vendor/github.com/longhorn/types/pkg/generated/spdkrpc/spdk.pb.go is excluded by !**/*.pb.go, !**/generated/**, !vendor/**
  • vendor/github.com/longhorn/types/pkg/generated/spdkrpc/spdk_grpc.pb.go is excluded by !**/*.pb.go, !**/generated/**, !vendor/**
  • vendor/github.com/matttproud/golang_protobuf_extensions/v2/NOTICE is excluded by !vendor/**
  • vendor/github.com/matttproud/golang_protobuf_extensions/v2/pbutil/.gitignore is excluded by !vendor/**
  • vendor/github.com/matttproud/golang_protobuf_extensions/v2/pbutil/Makefile is excluded by !vendor/**
  • vendor/github.com/matttproud/golang_protobuf_extensions/v2/pbutil/decode.go is excluded by !vendor/**
  • vendor/github.com/matttproud/golang_protobuf_extensions/v2/pbutil/doc.go is excluded by !vendor/**
  • vendor/github.com/matttproud/golang_protobuf_extensions/v2/pbutil/encode.go is excluded by !vendor/**
  • vendor/github.com/moby/sys/mountinfo/mounted_linux.go is excluded by !vendor/**
  • vendor/github.com/moby/sys/userns/LICENSE is excluded by !vendor/**
  • vendor/github.com/moby/sys/userns/userns.go is excluded by !vendor/**
  • vendor/github.com/moby/sys/userns/userns_linux.go is excluded by !vendor/**
  • vendor/github.com/moby/sys/userns/userns_linux_fuzzer.go is excluded by !vendor/**
  • vendor/github.com/moby/sys/userns/userns_unsupported.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/NOTICE is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/blkio_device.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/config.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/hugepage_limit.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/interface_priority_map.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_linux.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/network.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/devices/device.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/user/user.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/userns/userns.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/userns/userns_deprecated.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/userns/userns_linux.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/userns/userns_maps.c is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/userns/userns_maps_linux.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runtime-spec/LICENSE is excluded by !vendor/**
  • vendor/github.com/opencontainers/runtime-spec/specs-go/config.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runtime-spec/specs-go/state.go is excluded by !vendor/**
  • vendor/github.com/opencontainers/runtime-spec/specs-go/version.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/NOTICE is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/go_collector.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/histogram.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/metric.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/process_collector.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/registry.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/summary.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_golang/prometheus/vec.go is excluded by !vendor/**
  • vendor/github.com/prometheus/client_model/go/metrics.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/github.com/prometheus/common/expfmt/decode.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/expfmt/encode.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/expfmt/expfmt.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/expfmt/openmetrics_create.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/expfmt/text_create.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/expfmt/text_parse.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt is excluded by !vendor/**
  • vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/alert.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/labels.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/labelset.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/labelset_string.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/metadata.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/metric.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/signature.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/silence.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/value.go is excluded by !vendor/**
  • vendor/github.com/prometheus/common/model/value_float.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/.golangci.yml is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/MAINTAINERS.md is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/Makefile.common is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/arp.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/buddyinfo.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/cpuinfo.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/crypto.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/fscache.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/ipvs.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/loadavg.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/mdstat.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/meminfo.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/mountinfo.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/mountstats.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/net_conntrackstat.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/net_ip_socket.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/net_sockstat.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/net_softnet.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/net_tls_stat.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/net_unix.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/net_wireless.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/proc.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/proc_limits.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/proc_ns.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/proc_psi.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/proc_smaps.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/proc_stat.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/proc_status.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/proc_sys.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/softirqs.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/stat.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/swaps.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/thread.go is excluded by !vendor/**
  • vendor/github.com/prometheus/procfs/zoneinfo.go is excluded by !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go is excluded by !vendor/**
  • vendor/modules.txt is excluded by !vendor/**
📒 Files selected for processing (7)
  • pkg/api/backing_image.go (1 hunks)
  • pkg/client/instance.go (2 hunks)
  • pkg/client/proxy_backing_image.go (1 hunks)
  • pkg/instance/instance.go (1 hunks)
  • pkg/meta/version.go (2 hunks)
  • pkg/proxy/backing_image.go (1 hunks)
  • pkg/proxy/proxy.go (2 hunks)
🔇 Additional comments (9)
pkg/api/backing_image.go (1)

1-6: LGTM!

The package name and imports are appropriate for the functionality being implemented.

pkg/meta/version.go (3)

15-18: LGTM! API version constants are well-defined.

The new backing image service API version constants follow the established pattern and are appropriately initialized to version 1 for a new service.


74-81: LGTM! Version output struct is well-defined.

The BackingImageServiceVersionOutput struct follows the established pattern and includes appropriate JSON tags for serialization.


15-18: Verify version compatibility checks.

Let's ensure the new version constants are properly integrated into compatibility checks across the codebase.

Also applies to: 74-92

pkg/proxy/proxy.go (3)

9-13: LGTM: Import additions are appropriate

The new imports for error handling and gRPC status codes are necessary for the SPDK client integration and follow Go conventions.


76-79: LGTM: Robust error handling for SPDK client initialization

The error handling is well-implemented:

  • Uses appropriate gRPC status codes
  • Provides good context through error wrapping
  • Returns meaningful error messages to the client

86-88: LGTM: Clean initialization of SPDK fields

The initialization of the SPDK-related fields is clean and follows the established pattern in the struct initialization.

pkg/client/instance.go (1)

156-160: Verify backward compatibility and existing instance handling

The addition of BackingImageName to spdkInstanceSpec needs verification:

  1. Ensure existing instances without BackingImageName continue to work
  2. Verify if any default value is needed when BackingImageName is not specified
  3. Check if this change requires API version bump
✅ Verification successful

Based on the search results, I can now provide a definitive response about the BackingImageName field addition:

BackingImageName field is safely handled with proper backward compatibility

The codebase analysis shows that:

  1. BackingImageName is an optional field - the code checks for empty string before using it (if r.BackingImageName != "")
  2. Existing instances without BackingImageName continue to work as the field defaults to empty string
  3. The field is properly integrated into the SPDK instance creation path with appropriate error handling
  4. No API version bump is required as this is an additive, backward-compatible change
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing usage patterns and potential breaking changes

# Look for existing replica creation patterns
rg -A 5 "InstanceCreate.*InstanceTypeReplica" --type go

# Check for version handling in the codebase
ast-grep --pattern 'const.*Version.*=.*' 

Length of output: 100


Script:

#!/bin/bash
# Let's try a different approach to analyze the changes

# Search for BackingImageName usage in the codebase
rg "BackingImageName" --type go -B 2 -A 2

# Look for SPDK instance related structs and interfaces
rg "type.*Instance" --type go -A 5

# Check for version related constants specifically in API packages
fd -e go -E 'vendor/*' --exec grep -l "Version" {} \; | xargs cat

Length of output: 113200

pkg/instance/instance.go (1)

160-163: LGTM! Implementation correctly adds backing image support.

The modification properly integrates the backing image name parameter into the ReplicaCreate call while maintaining consistent error handling.

Let's verify the consistency of backing image handling across the codebase:

✅ Verification successful

Let me gather more specific information about the ReplicaCreate implementation and usage.


Let me check the ReplicaCreateRequest definition to verify the backing image parameter handling.


Based on the gathered information, I can now provide the final response:

Verified: BackingImageName parameter is properly integrated

The modification to include BackingImageName in the ReplicaCreate call is correctly implemented and consistent with the codebase architecture:

  • The parameter is properly defined in the SPDK RPC protocol (ReplicaCreateRequest struct)
  • The backing image integration is consistently handled across the client, instance, and SPDK components
  • The change maintains compatibility with existing interfaces while extending functionality
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify backing image integration across the codebase
# Check for other occurrences of ReplicaCreate to ensure consistent parameter usage
ast-grep --pattern 'ReplicaCreate($$$)'

# Check for related backing image handling
rg -l "BackingImage" --type go

Length of output: 2097


Script:

#!/bin/bash
# Check for ReplicaCreate implementation and interface definition
rg "ReplicaCreate.*\(" -A 5 --type go

# Check for backing image related structs and types
ast-grep --pattern 'type $_ struct {
  $$$
  BackingImage$_ $_
  $$$
}'

Length of output: 41608


Script:

#!/bin/bash
# Check ReplicaCreateRequest definition in SPDK RPC
rg "type ReplicaCreateRequest struct" -A 10 --type go

# Check for backing image parameter in the SPDK server implementation
rg "BackingImageName.*string" --type go

Length of output: 6322

Comment on lines +25 to +40
func RPCToBackingImage(obj *rpc.SPDKBackingImageResponse) *BackingImage {
return &BackingImage{
Name: obj.Spec.Name,
BackingImageUUID: obj.Spec.BackingImageUuid,
DiskUUID: obj.Spec.DiskUuid,
Size: obj.Spec.Size,
ExpectedChecksum: obj.Spec.Checksum,

Status: BackingImageStatus{
Progress: int(obj.Status.Progress),
State: obj.Status.State,
CurrentChecksum: obj.Status.Checksum,
ErrorMsg: obj.Status.ErrorMsg,
},
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation and error handling.

The conversion function should validate its input and the resulting BackingImage.

Consider this implementation:

-func RPCToBackingImage(obj *rpc.SPDKBackingImageResponse) *BackingImage {
+func RPCToBackingImage(obj *rpc.SPDKBackingImageResponse) (*BackingImage, error) {
+       if obj == nil {
+               return nil, fmt.Errorf("cannot convert nil SPDKBackingImageResponse")
+       }
+       if obj.Spec == nil {
+               return nil, fmt.Errorf("backing image spec is nil")
+       }
+
        bi := &BackingImage{
                Name:             obj.Spec.Name,
                BackingImageUUID: obj.Spec.BackingImageUuid,
                DiskUUID:         obj.Spec.DiskUuid,
                Size:             obj.Spec.Size,
                ExpectedChecksum: obj.Spec.Checksum,

                Status: BackingImageStatus{
                        Progress:        int(obj.Status.Progress),
                        State:           obj.Status.State,
                        CurrentChecksum: obj.Status.Checksum,
                        ErrorMsg:        obj.Status.ErrorMsg,
                },
        }
+       
+       if err := bi.Validate(); err != nil {
+               return nil, fmt.Errorf("invalid backing image after conversion: %v", err)
+       }
+       
-       return bi
+       return bi, nil
}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +42 to +48
func RPCToBackingImageList(obj *rpc.SPDKBackingImageListResponse) map[string]*BackingImage {
ret := map[string]*BackingImage{}
for name, bi := range obj.BackingImages {
ret[name] = RPCToBackingImage(bi)
}
return ret
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling and consider memory optimization.

The list conversion should handle errors and optimize memory allocation.

Consider this implementation:

-func RPCToBackingImageList(obj *rpc.SPDKBackingImageListResponse) map[string]*BackingImage {
+func RPCToBackingImageList(obj *rpc.SPDKBackingImageListResponse) (map[string]*BackingImage, error) {
+       if obj == nil {
+               return nil, fmt.Errorf("cannot convert nil SPDKBackingImageListResponse")
+       }
+
-       ret := map[string]*BackingImage{}
+       ret := make(map[string]*BackingImage, len(obj.BackingImages))
        for name, bi := range obj.BackingImages {
-               ret[name] = RPCToBackingImage(bi)
+               converted, err := RPCToBackingImage(bi)
+               if err != nil {
+                       return nil, fmt.Errorf("failed to convert backing image %s: %v", name, err)
+               }
+               ret[name] = converted
        }
-       return ret
+       return ret, nil
}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +18 to +23
type BackingImageStatus struct {
Progress int `json:"progress"`
State string `json:"state"`
CurrentChecksum string `json:"currentChecksum"`
ErrorMsg string `json:"errorMsg"`
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider using enum for State and fix JSON tag inconsistency.

Two suggestions for improvement:

  1. The State field should be an enumerated type for type safety
  2. The CurrentChecksum JSON tag doesn't follow the snake_case convention used by other fields

Consider this implementation:

+// BackingImageState represents the possible states of a backing image
+type BackingImageState string
+
+const (
+       BackingImageStateInitial    BackingImageState = "initial"
+       BackingImageStateReady      BackingImageState = "ready"
+       BackingImageStateError      BackingImageState = "error"
+       // Add other states as needed
+)

 type BackingImageStatus struct {
        Progress        int    `json:"progress"`
-       State           string `json:"state"`
+       State           BackingImageState `json:"state"`
        CurrentChecksum string `json:"currentChecksum"`
+       CurrentChecksum string `json:"current_checksum"`
        ErrorMsg        string `json:"errorMsg"`
+       ErrorMsg        string `json:"error_msg"`
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +50 to +62
type BackingImageStream struct {
stream rpc.ProxyEngineService_SPDKBackingImageWatchClient
}

func NewBackingImageStream(stream rpc.ProxyEngineService_SPDKBackingImageWatchClient) *BackingImageStream {
return &BackingImageStream{
stream,
}
}

func (s *BackingImageStream) Recv() (*emptypb.Empty, error) {
return s.stream.Recv()
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance stream management with context and cleanup.

The stream implementation should handle context cancellation and provide proper cleanup.

Consider this implementation:

+// BackingImageStream wraps the SPDK backing image watch stream
 type BackingImageStream struct {
        stream rpc.ProxyEngineService_SPDKBackingImageWatchClient
+       done   chan struct{}
 }

 func NewBackingImageStream(stream rpc.ProxyEngineService_SPDKBackingImageWatchClient) *BackingImageStream {
        return &BackingImageStream{
                stream: stream,
+               done:   make(chan struct{}),
        }
 }

-func (s *BackingImageStream) Recv() (*emptypb.Empty, error) {
+func (s *BackingImageStream) Recv(ctx context.Context) (*emptypb.Empty, error) {
+       select {
+       case <-ctx.Done():
+               return nil, ctx.Err()
+       case <-s.done:
+               return nil, fmt.Errorf("stream closed")
+       default:
                return s.stream.Recv()
+       }
+}
+
+// Close closes the backing image stream
+func (s *BackingImageStream) Close() error {
+       close(s.done)
+       return nil
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type BackingImageStream struct {
stream rpc.ProxyEngineService_SPDKBackingImageWatchClient
}
func NewBackingImageStream(stream rpc.ProxyEngineService_SPDKBackingImageWatchClient) *BackingImageStream {
return &BackingImageStream{
stream,
}
}
func (s *BackingImageStream) Recv() (*emptypb.Empty, error) {
return s.stream.Recv()
}
// BackingImageStream wraps the SPDK backing image watch stream
type BackingImageStream struct {
stream rpc.ProxyEngineService_SPDKBackingImageWatchClient
done chan struct{}
}
func NewBackingImageStream(stream rpc.ProxyEngineService_SPDKBackingImageWatchClient) *BackingImageStream {
return &BackingImageStream{
stream: stream,
done: make(chan struct{}),
}
}
func (s *BackingImageStream) Recv(ctx context.Context) (*emptypb.Empty, error) {
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-s.done:
return nil, fmt.Errorf("stream closed")
default:
return s.stream.Recv()
}
}
// Close closes the backing image stream
func (s *BackingImageStream) Close() error {
close(s.done)
return nil
}

Comment on lines +70 to +71
return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to create spdk backing image due to parameters missing")
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix incorrect error message in SPDKBackingImageGet

The error message in SPDKBackingImageGet incorrectly states "failed to create spdk backing image due to parameters missing", but this function is for retrieving backing images. Update the error message to accurately reflect the get operation.

Apply the following diff to correct the error message:

- return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to create spdk backing image due to parameters missing")
+ return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to get spdk backing image due to missing parameters")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to create spdk backing image due to parameters missing")
}
return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to get spdk backing image due to missing parameters")
}

Comment on lines +58 to +59
return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to create spdk backing image due to parameters missing")
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix incorrect error message in SPDKBackingImageDelete

The error message in SPDKBackingImageDelete incorrectly states "failed to create spdk backing image due to parameters missing", but this function is responsible for deleting backing images. Update the error message to accurately reflect the delete operation.

Apply the following diff to correct the error message:

- return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to create spdk backing image due to parameters missing")
+ return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to delete spdk backing image due to missing parameters")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to create spdk backing image due to parameters missing")
}
return nil, grpcstatus.Error(grpccodes.InvalidArgument, "failed to delete spdk backing image due to missing parameters")
}

func (p *Proxy) watchSPDKBackingImage(ctx context.Context, req *emptypb.Empty, client *spdkclient.SPDKClient, notifyChan chan struct{}) error {
logrus.Info("Start watching SPDK replicas")

notifier, err := client.BackingImageWatch(context.Background())
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use the provided context instead of context.Background()

In watchSPDKBackingImage, the call to client.BackingImageWatch uses context.Background(), which ignores cancellation and timeout signals from the parent context. This can lead to resource leaks if the parent context is canceled.

Replace context.Background() with the provided ctx to ensure proper context propagation.

- notifier, err := client.BackingImageWatch(context.Background())
+ notifier, err := client.BackingImageWatch(ctx)

This change ensures that the BackingImageWatch operation respects cancellations and timeouts, preventing potential resource leaks.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
notifier, err := client.BackingImageWatch(context.Background())
notifier, err := client.BackingImageWatch(ctx)

Comment on lines +103 to +104
done <- struct{}{}
return grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to create SPDK client").Error())
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Prevent potential deadlock when spdkClient creation fails

In SPDKBackingImageWatch, if an error occurs during the creation of spdkClient and done <- struct{}{} is called, it may cause a deadlock because the goroutine that reads from done hasn't started yet. Since done is an unbuffered channel, the send operation will block indefinitely.

To fix this issue, rearrange the code to start the goroutine before attempting to create spdkClient, and avoid sending to done when an error occurs.

Apply the following changes:

done := make(chan struct{})

+ go func() {
+     <-done
+     logrus.Info("Stopped clients for watching SPDK backing image")
+     if spdkClient != nil {
+         spdkClient.Close()
+     }
+     close(done)
+ }()

// Create a client for watching SPDK backing image
spdkClient, err := spdkclient.NewSPDKClient(p.spdkServiceAddress)
if err != nil {
-    done <- struct{}{}
    return grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to create SPDK client").Error())
}

This ensures the goroutine is ready to receive from done before any potential send operation. Also, we check if spdkClient is not nil before calling spdkClient.Close().

Committable suggestion skipped: line range outside the PR's diff.

Copy link

mergify bot commented Nov 30, 2024

This pull request is now in conflict. Could you fix it @ChanYiLin? 🙏

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.

1 participant