Add GoVPP integration and GetVPPInfo gRPC call
VPP client (internal/vpp/) - New package managing connections to both VPP API and stats sockets, treated as a unit: if either drops, both are torn down and re-established together. - Run() loop: connect, fetch version via vpe.ShowVersion, read /sys/boottime from the stats segment, log vpp-connect, then monitor with control_ping every 10s. On failure, disconnect both, retry after 5s. - Registers as client name "vpp-maglev" (visible in VPP's "show api clients"). - Flags: --vpp-api-addr (default /run/vpp/api.sock) and --vpp-stats-addr (default /run/vpp/stats.sock). Empty api addr disables VPP integration entirely. gRPC / proto - Add GetVPPInfo RPC returning VPPInfo: version, build_date, build_directory, pid, boottime_ns, connecttime_ns. Both times are unix timestamps in nanoseconds — the client computes durations locally for display. - Returns codes.Unavailable if VPP is disabled or not connected. maglevc - Add 'show vpp info' command displaying version, build-date, build-dir, vpp-pid, vpp-boottime (with duration), and connected time (with duration).
This commit is contained in:
@@ -33,6 +33,7 @@ const (
|
||||
Maglev_WatchEvents_FullMethodName = "/maglev.Maglev/WatchEvents"
|
||||
Maglev_CheckConfig_FullMethodName = "/maglev.Maglev/CheckConfig"
|
||||
Maglev_ReloadConfig_FullMethodName = "/maglev.Maglev/ReloadConfig"
|
||||
Maglev_GetVPPInfo_FullMethodName = "/maglev.Maglev/GetVPPInfo"
|
||||
)
|
||||
|
||||
// MaglevClient is the client API for Maglev service.
|
||||
@@ -55,6 +56,7 @@ type MaglevClient interface {
|
||||
WatchEvents(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Event], error)
|
||||
CheckConfig(ctx context.Context, in *CheckConfigRequest, opts ...grpc.CallOption) (*CheckConfigResponse, error)
|
||||
ReloadConfig(ctx context.Context, in *ReloadConfigRequest, opts ...grpc.CallOption) (*ReloadConfigResponse, error)
|
||||
GetVPPInfo(ctx context.Context, in *GetVPPInfoRequest, opts ...grpc.CallOption) (*VPPInfo, error)
|
||||
}
|
||||
|
||||
type maglevClient struct {
|
||||
@@ -214,6 +216,16 @@ func (c *maglevClient) ReloadConfig(ctx context.Context, in *ReloadConfigRequest
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *maglevClient) GetVPPInfo(ctx context.Context, in *GetVPPInfoRequest, opts ...grpc.CallOption) (*VPPInfo, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(VPPInfo)
|
||||
err := c.cc.Invoke(ctx, Maglev_GetVPPInfo_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MaglevServer is the server API for Maglev service.
|
||||
// All implementations must embed UnimplementedMaglevServer
|
||||
// for forward compatibility.
|
||||
@@ -234,6 +246,7 @@ type MaglevServer interface {
|
||||
WatchEvents(*WatchRequest, grpc.ServerStreamingServer[Event]) error
|
||||
CheckConfig(context.Context, *CheckConfigRequest) (*CheckConfigResponse, error)
|
||||
ReloadConfig(context.Context, *ReloadConfigRequest) (*ReloadConfigResponse, error)
|
||||
GetVPPInfo(context.Context, *GetVPPInfoRequest) (*VPPInfo, error)
|
||||
mustEmbedUnimplementedMaglevServer()
|
||||
}
|
||||
|
||||
@@ -286,6 +299,9 @@ func (UnimplementedMaglevServer) CheckConfig(context.Context, *CheckConfigReques
|
||||
func (UnimplementedMaglevServer) ReloadConfig(context.Context, *ReloadConfigRequest) (*ReloadConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ReloadConfig not implemented")
|
||||
}
|
||||
func (UnimplementedMaglevServer) GetVPPInfo(context.Context, *GetVPPInfoRequest) (*VPPInfo, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetVPPInfo not implemented")
|
||||
}
|
||||
func (UnimplementedMaglevServer) mustEmbedUnimplementedMaglevServer() {}
|
||||
func (UnimplementedMaglevServer) testEmbeddedByValue() {}
|
||||
|
||||
@@ -552,6 +568,24 @@ func _Maglev_ReloadConfig_Handler(srv interface{}, ctx context.Context, dec func
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Maglev_GetVPPInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetVPPInfoRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MaglevServer).GetVPPInfo(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Maglev_GetVPPInfo_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MaglevServer).GetVPPInfo(ctx, req.(*GetVPPInfoRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Maglev_ServiceDesc is the grpc.ServiceDesc for Maglev service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -611,6 +645,10 @@ var Maglev_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "ReloadConfig",
|
||||
Handler: _Maglev_ReloadConfig_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetVPPInfo",
|
||||
Handler: _Maglev_GetVPPInfo_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user