feat: add vsock network type support (#1303)
So we support connecting dfdaemon running on host outside of VM via virtio-vsock device. Signed-off-by: Eryu Guan <eguan@linux.alibaba.com>
This commit is contained in:
parent
8f26e3213c
commit
0bc0d3b7ea
2
go.mod
2
go.mod
|
|
@ -41,6 +41,7 @@ require (
|
||||||
github.com/jarcoal/httpmock v1.0.8
|
github.com/jarcoal/httpmock v1.0.8
|
||||||
github.com/looplab/fsm v0.3.0
|
github.com/looplab/fsm v0.3.0
|
||||||
github.com/mcuadros/go-gin-prometheus v0.1.0
|
github.com/mcuadros/go-gin-prometheus v0.1.0
|
||||||
|
github.com/mdlayher/vsock v1.1.1
|
||||||
github.com/mitchellh/mapstructure v1.4.1
|
github.com/mitchellh/mapstructure v1.4.1
|
||||||
github.com/montanaflynn/stats v0.6.6
|
github.com/montanaflynn/stats v0.6.6
|
||||||
github.com/onsi/ginkgo/v2 v2.1.0
|
github.com/onsi/ginkgo/v2 v2.1.0
|
||||||
|
|
@ -155,6 +156,7 @@ require (
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||||
|
github.com/mdlayher/socket v0.2.0 // indirect
|
||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -642,6 +642,10 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182aff
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||||
github.com/mcuadros/go-gin-prometheus v0.1.0 h1:JNoWKvw/u9tyRJ8BL9ZJvfiXU8IHUw8gCvcf/5L8tnI=
|
github.com/mcuadros/go-gin-prometheus v0.1.0 h1:JNoWKvw/u9tyRJ8BL9ZJvfiXU8IHUw8gCvcf/5L8tnI=
|
||||||
github.com/mcuadros/go-gin-prometheus v0.1.0/go.mod h1:ezECAsiHtCRIa+6Ii8THg7G7RJvpO4S19d499UkEE3s=
|
github.com/mcuadros/go-gin-prometheus v0.1.0/go.mod h1:ezECAsiHtCRIa+6Ii8THg7G7RJvpO4S19d499UkEE3s=
|
||||||
|
github.com/mdlayher/socket v0.2.0 h1:EY4YQd6hTAg2tcXF84p5DTHazShE50u5HeBzBaNgjkA=
|
||||||
|
github.com/mdlayher/socket v0.2.0/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
|
||||||
|
github.com/mdlayher/vsock v1.1.1 h1:8lFuiXQnmICBrCIIA9PMgVSke6Fg6V4+r0v7r55k88I=
|
||||||
|
github.com/mdlayher/vsock v1.1.1/go.mod h1:Y43jzcy7KM3QB+/FK15pfqGxDMCMzUXWegEfIbSM18U=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,13 @@ import (
|
||||||
type NetworkType string
|
type NetworkType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TCP NetworkType = "tcp"
|
TCP NetworkType = "tcp"
|
||||||
UNIX NetworkType = "unix"
|
UNIX NetworkType = "unix"
|
||||||
|
VSOCK NetworkType = "vsock"
|
||||||
|
|
||||||
|
TCPEndpointPrefix string = "dns:///"
|
||||||
|
UnixEndpointPrefix string = "unix://"
|
||||||
|
VsockEndpointPrefix string = "vsock://"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NetAddr struct {
|
type NetAddr struct {
|
||||||
|
|
@ -39,9 +44,11 @@ type NetAddr struct {
|
||||||
func (n NetAddr) GetEndpoint() string {
|
func (n NetAddr) GetEndpoint() string {
|
||||||
switch n.Type {
|
switch n.Type {
|
||||||
case UNIX:
|
case UNIX:
|
||||||
return "unix://" + n.Addr
|
return UnixEndpointPrefix + n.Addr
|
||||||
|
case VSOCK:
|
||||||
|
return VsockEndpointPrefix + n.Addr
|
||||||
default:
|
default:
|
||||||
return "dns:///" + n.Addr
|
return TCPEndpointPrefix + n.Addr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,15 @@ func GetClientByAddr(addrs []dfnet.NetAddr, opts ...grpc.DialOption) (DaemonClie
|
||||||
if len(addrs) == 0 {
|
if len(addrs) == 0 {
|
||||||
return nil, errors.New("address list of daemon is empty")
|
return nil, errors.New("address list of daemon is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialOpts, err := rpc.VsockDialerOption(addrs, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
dc := &daemonClient{
|
dc := &daemonClient{
|
||||||
rpc.NewConnection(context.Background(), "daemon-static", addrs, []rpc.ConnOption{
|
rpc.NewConnection(context.Background(), "daemon-static", addrs, []rpc.ConnOption{
|
||||||
rpc.WithConnExpireTime(60 * time.Second),
|
rpc.WithConnExpireTime(60 * time.Second),
|
||||||
rpc.WithDialOption(opts),
|
rpc.WithDialOption(dialOpts),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
return dc, nil
|
return dc, nil
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 The Dragonfly Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mdlayher/vsock"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
|
"d7y.io/dragonfly/v2/pkg/dfnet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VsockDialer is the dialer for vsock, it expects `address` to be in dfnet.NetAddr.GetEndpoint()
|
||||||
|
// format, that is "vsock://cid:port"
|
||||||
|
func VsockDialer(_ctx context.Context, address string) (net.Conn, error) {
|
||||||
|
addrStr := strings.TrimPrefix(address, dfnet.VsockEndpointPrefix)
|
||||||
|
addr := strings.Split(addrStr, ":")
|
||||||
|
if len(addr) != 2 {
|
||||||
|
return nil, fmt.Errorf("invalid vsock address (%s), expected %scid:port", address, dfnet.VsockEndpointPrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
cid, err := strconv.ParseUint(addr[0], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to convert %q to vsock cid", addr[0])
|
||||||
|
}
|
||||||
|
port, err := strconv.ParseUint(addr[1], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to convert %q to vsock port", addr[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := vsock.Dial(uint32(cid), uint32(port), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to dial vsock %v:%v, address %s", uint32(cid), uint32(port), address)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If `addrs` are all vsock addresses, add rpc.VsockDialer to DialOption, and return error if addrs
|
||||||
|
// have mixed vsock and other connection types.
|
||||||
|
func VsockDialerOption(addrs []dfnet.NetAddr, opts []grpc.DialOption) ([]grpc.DialOption, error) {
|
||||||
|
var prevType dfnet.NetworkType
|
||||||
|
hasVsock := false
|
||||||
|
for n, a := range addrs {
|
||||||
|
if a.Type != dfnet.VSOCK {
|
||||||
|
prevType = a.Type
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hasVsock = true
|
||||||
|
if n > 0 && prevType != dfnet.VSOCK {
|
||||||
|
return nil, fmt.Errorf("addrs(%v) have mixed vsock and other types", addrs)
|
||||||
|
}
|
||||||
|
prevType = a.Type
|
||||||
|
}
|
||||||
|
dialOpts := opts
|
||||||
|
if hasVsock {
|
||||||
|
dialOpts = append(opts, grpc.WithContextDialer(VsockDialer))
|
||||||
|
}
|
||||||
|
return dialOpts, nil
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue