Skip to content

Commit

Permalink
feat(volume): add remount read only volume grpc
Browse files Browse the repository at this point in the history
ref: longhorn/longhorn 7843

Signed-off-by: Jack Lin <jack.lin@suse.com>
  • Loading branch information
ChanYiLin committed Feb 7, 2024
1 parent 1f07374 commit 2cbdc2a
Show file tree
Hide file tree
Showing 8 changed files with 455 additions and 273 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ def __init__(self, channel):
request_serializer=github_dot_com_dot_longhorn_dot_longhorn__instance__manager_dot_pkg_dot_imrpc_dot_proxy__pb2.ProxyEngineRequest.SerializeToString,
response_deserializer=github_dot_com_dot_longhorn_dot_longhorn__instance__manager_dot_pkg_dot_imrpc_dot_proxy__pb2.EngineMetricsGetProxyResponse.FromString,
)
self.RemountReadOnlyVolume = channel.unary_unary(
'/imrpc.ProxyEngineService/RemountReadOnlyVolume',
request_serializer=github_dot_com_dot_longhorn_dot_longhorn__instance__manager_dot_pkg_dot_imrpc_dot_proxy__pb2.RemountVolumeRequest.SerializeToString,
response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
)


class ProxyEngineServiceServicer(object):
Expand Down Expand Up @@ -361,6 +366,12 @@ def MetricsGet(self, request, context):
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')

def RemountReadOnlyVolume(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')


def add_ProxyEngineServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
Expand Down Expand Up @@ -519,6 +530,11 @@ def add_ProxyEngineServiceServicer_to_server(servicer, server):
request_deserializer=github_dot_com_dot_longhorn_dot_longhorn__instance__manager_dot_pkg_dot_imrpc_dot_proxy__pb2.ProxyEngineRequest.FromString,
response_serializer=github_dot_com_dot_longhorn_dot_longhorn__instance__manager_dot_pkg_dot_imrpc_dot_proxy__pb2.EngineMetricsGetProxyResponse.SerializeToString,
),
'RemountReadOnlyVolume': grpc.unary_unary_rpc_method_handler(
servicer.RemountReadOnlyVolume,
request_deserializer=github_dot_com_dot_longhorn_dot_longhorn__instance__manager_dot_pkg_dot_imrpc_dot_proxy__pb2.RemountVolumeRequest.FromString,
response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'imrpc.ProxyEngineService', rpc_method_handlers)
Expand Down Expand Up @@ -1055,3 +1071,20 @@ def MetricsGet(request,
github_dot_com_dot_longhorn_dot_longhorn__instance__manager_dot_pkg_dot_imrpc_dot_proxy__pb2.EngineMetricsGetProxyResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

@staticmethod
def RemountReadOnlyVolume(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/imrpc.ProxyEngineService/RemountReadOnlyVolume',
github_dot_com_dot_longhorn_dot_longhorn__instance__manager_dot_pkg_dot_imrpc_dot_proxy__pb2.RemountVolumeRequest.SerializeToString,
google_dot_protobuf_dot_empty__pb2.Empty.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
16 changes: 16 additions & 0 deletions pkg/client/proxy_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,19 @@ func (c *ProxyClient) VolumeSnapshotMaxSizeSet(dataEngine, engineName, volumeNam

return nil
}

func (c *ProxyClient) RemountReadOnlyVolume(volumeName string) (err error) {
if volumeName == "" {
return fmt.Errorf("failed to remount volume, volume name is empty")
}

req := &rpc.RemountVolumeRequest{
VolumeName: volumeName,
}

_, err = c.service.RemountReadOnlyVolume(getContextWithGRPCTimeout(c.ctx), req)
if err != nil {
return err
}
return nil
}
626 changes: 366 additions & 260 deletions pkg/imrpc/proxy.pb.go

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions pkg/imrpc/proxy.proto
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ service ProxyEngineService {
rpc ReplicaModeUpdate(EngineReplicaModeUpdateRequest) returns (google.protobuf.Empty);

rpc MetricsGet(ProxyEngineRequest) returns (EngineMetricsGetProxyResponse);
rpc RemountReadOnlyVolume(RemountVolumeRequest) returns (google.protobuf.Empty);
}

message ProxyEngineRequest{
Expand Down Expand Up @@ -293,3 +294,7 @@ message EngineSnapshotHashStatusProxyResponse {
message EngineMetricsGetProxyResponse {
ptypes.Metrics metrics = 1;
}

message RemountVolumeRequest {
string volume_name = 1;
}
26 changes: 26 additions & 0 deletions pkg/proxy/volume.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package proxy

import (
"crypto/sha256"
"encoding/hex"
"os/exec"

"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/net/context"
Expand All @@ -12,6 +16,7 @@ import (
eptypes "github.com/longhorn/longhorn-engine/proto/ptypes"

rpc "github.com/longhorn/longhorn-instance-manager/pkg/imrpc"
"github.com/longhorn/longhorn-instance-manager/pkg/util"
)

func (p *Proxy) VolumeGet(ctx context.Context, req *rpc.ProxyEngineRequest) (resp *rpc.EngineVolumeGetProxyResponse, err error) {
Expand Down Expand Up @@ -308,3 +313,24 @@ func (ops V2DataEngineProxyOps) VolumeSnapshotMaxSizeSet(ctx context.Context, re
/* TODO: Implement this */
return &emptypb.Empty{}, nil
}

func (p *Proxy) RemountReadOnlyVolume(ctx context.Context, req *rpc.RemountVolumeRequest) (resp *emptypb.Empty, err error) {
volumeName := req.VolumeName
volumeNameSHA := sha256.Sum256([]byte(volumeName))
volumeNameSHAStr := hex.EncodeToString(volumeNameSHA[:])

volumeMountPointMap, err := util.GetVolumeMountPointMap()
if err != nil {
logrus.WithError(err).Warn("Failed to get all volume mount points")
}

if mp, exists := volumeMountPointMap[volumeNameSHAStr]; exists {
cmd := exec.CommandContext(ctx, "mount", "-o", "remount,rw", mp.Path)
if out, err := cmd.CombinedOutput(); err != nil {
return nil, grpcstatus.Errorf(grpccodes.Internal, "remount failed with output: %v", out)
}

}

return &emptypb.Empty{}, nil
}
2 changes: 0 additions & 2 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,5 @@ const (
)

const (
GlobalMountPathPattern = "/host/var/lib/kubelet/plugins/kubernetes.io/csi/driver.longhorn.io/*/globalmount"

EngineConditionFilesystemReadOnly = "FilesystemReadOnly"
)
12 changes: 4 additions & 8 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"net"
"os"
"os/exec"
"path"
"regexp"
"strconv"
"strings"
"time"
Expand All @@ -18,8 +18,6 @@ import (
"k8s.io/mount-utils"

spdkhelpertypes "github.com/longhorn/go-spdk-helper/pkg/types"

"github.com/longhorn/longhorn-instance-manager/pkg/types"
)

const (
Expand Down Expand Up @@ -158,12 +156,10 @@ func GetVolumeMountPointMap() (map[string]mount.MountPoint, error) {
return nil, err
}

regex := regexp.MustCompile(`.*/globalmount$`)

for _, mp := range mountPoints {
match, err := path.Match(types.GlobalMountPathPattern, mp.Path)
if err != nil {
return nil, err
}
if match {
if regex.MatchString(mp.Path) {
volumeNameSHAStr := GetVolumeNameSHAStrFromPath(mp.Path)
volumeMountPointMap[volumeNameSHAStr] = mp
}
Expand Down

0 comments on commit 2cbdc2a

Please sign in to comment.