API, ETCD et RAFT passe en tant que package

This commit is contained in:
Mickael BOURNEUF 2025-02-16 14:47:35 +01:00
parent 861f53b6c9
commit e6c07d9a0a
19 changed files with 5468 additions and 7 deletions

View File

@ -25,7 +25,7 @@ type Client struct {
}
func NewAMQP() (*Client, error) {
config, _ := config.NewConfig()
config, _ := config.New()
amqp_config := amqp091.Config{
Properties: amqp091.NewConnectionProperties(),

93
pkg/api/domain.go Normal file
View File

@ -0,0 +1,93 @@
package api
import (
"context"
"regexp"
"strconv"
"time"
"deevirt.fr/compute/pkg/api/proto"
"deevirt.fr/compute/pkg/config"
clientv3 "go.etcd.io/etcd/client/v3"
)
type Domain struct {
Config *config.Config
Etcd *clientv3.Client
proto.UnimplementedDomainServer
}
func (d *Domain) List(ctx context.Context, in *proto.DomainListAllRequest) (*proto.DomainListAllResponse, error) {
var domains = []*proto.DomainListResponse{}
ctx_etcd, cancel := context.WithTimeout(context.Background(), 5*time.Second)
resp, _ := d.Etcd.Get(ctx_etcd, "/cluster/"+d.Config.ClusterID+"/domain", clientv3.WithPrefix(), clientv3.WithKeysOnly())
cancel()
re := regexp.MustCompile(`domain/(?P<domainID>[a-zA-Z1-9-]+)$`)
for _, data := range resp.Kvs {
key := string(data.Key[:])
if re.MatchString(key) {
matches := re.FindStringSubmatch(key)
index := re.SubexpIndex("domainID")
domain, _ := d.Get(context.Background(), &proto.DomainListRequest{
DomainId: matches[index],
})
domains = append(domains, domain)
}
}
return &proto.DomainListAllResponse{
Domains: domains,
}, nil
}
func (d *Domain) Get(ctx context.Context, in *proto.DomainListRequest) (*proto.DomainListResponse, error) {
ctx_etcd, cancel := context.WithTimeout(context.Background(), 5*time.Second)
resp_config, _ := d.Etcd.Get(ctx_etcd, "/cluster/"+d.Config.ClusterID+"/domain/"+in.DomainId)
resp_state, _ := d.Etcd.Get(ctx_etcd, "/cluster/"+d.Config.ClusterID+"/domain/"+in.DomainId+"/state")
cancel()
state, _ := strconv.ParseInt(string(resp_state.Kvs[0].Value), 10, 64)
return &proto.DomainListResponse{
DomainId: in.DomainId,
Config: string(resp_config.Kvs[0].Value),
State: state,
}, nil
}
func (d *Domain) Create(ctx context.Context, in *proto.DomainCreateRequest) (*proto.DomainCreateResponse, error) {
ctx_etcd, cancel := context.WithTimeout(context.Background(), 5*time.Second)
resp_config, _ := d.Etcd.Get(ctx_etcd, "/cluster/"+d.Config.ClusterID)
cancel()
println(string(resp_config.Kvs[0].Value))
/*if d.Config.LibvirtTLS {
libvirt_uri := "qemu+tls://"++"/system"
}
conn, err := libvirt.NewConnect("qemu:///system")
if err != nil {
log.Println("Connexion Error")
}
defer conn.Close()*/
/*
async def Create(self, request, context):
yield domain_pb2.DomainCreateResponse(progress=40)
async with Libvirt() as libvirt:
if await libvirt.define(request.config.decode()):
yield domain_pb2.DomainCreateResponse(progress=100)
else:
context.set_code(grpc.StatusCode.ALREADY_EXISTS)
*/
return &proto.DomainCreateResponse{}, nil
}

1088
pkg/api/proto/domain.pb.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
syntax="proto3";
option go_package = "./proto";
package deevirt;
// The greeting service definition.
service Domain {
rpc List (DomainListAllRequest) returns (DomainListAllResponse) {}
rpc Get (DomainListRequest) returns (DomainListResponse) {}
rpc Create (DomainCreateRequest) returns (DomainCreateResponse) {}
rpc Update (DomainUpdateRequest) returns (DomainUpdateResponse) {}
rpc Delete (DomainDeleteRequest) returns (DomainDeleteResponse) {}
rpc Power (DomainPowerRequest) returns (DomainPowerResponse) {}
}
message DomainListAllRequest {}
message DomainListAllResponse {
repeated DomainListResponse domains = 1;
}
message DomainListRequest {
string domain_id = 1;
}
message DomainListResponse {
string domain_id = 1;
string config = 2;
int64 state = 3;
}
message DomainCreateRequest {
string node_id = 1;
string config = 2;
}
message DomainCreateResponse {
int64 progress = 1;
}
service DomainDevicesGraphics {
rpc Console (DomainDevicesGraphicsConsoleRequest) returns (DomainDevicesGraphicsConsoleResponse) {}
}
message DomainUpdateRequest {
string vm_id = 1;
}
message DomainUpdateResponse {
}
message DomainDeleteRequest {
string vm_id = 1;
}
message DomainDeleteResponse {
}
enum DomainPower {
UNDEFINED = 0;
START = 1;
REBOOT = 2;
SHUTDOWN = 3;
PAUSE = 4;
RESUME = 5;
RESET = 6;
DESTROY = 7;
}
message DomainPowerRequest {
bytes vm_id = 1;
DomainPower action = 2;
}
message DomainPowerResponse {
}
message DomainDevicesGraphicsConsoleRequest {
bytes vm_id = 1;
}
message DomainDevicesGraphicsConsoleResponse {
string uri = 1;
}

View File

@ -0,0 +1,417 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v3.14.0
// source: proto/domain.proto
package proto
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
Domain_List_FullMethodName = "/deevirt.Domain/List"
Domain_Get_FullMethodName = "/deevirt.Domain/Get"
Domain_Create_FullMethodName = "/deevirt.Domain/Create"
Domain_Update_FullMethodName = "/deevirt.Domain/Update"
Domain_Delete_FullMethodName = "/deevirt.Domain/Delete"
Domain_Power_FullMethodName = "/deevirt.Domain/Power"
)
// DomainClient is the client API for Domain service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// The greeting service definition.
type DomainClient interface {
List(ctx context.Context, in *DomainListAllRequest, opts ...grpc.CallOption) (*DomainListAllResponse, error)
Get(ctx context.Context, in *DomainListRequest, opts ...grpc.CallOption) (*DomainListResponse, error)
Create(ctx context.Context, in *DomainCreateRequest, opts ...grpc.CallOption) (*DomainCreateResponse, error)
Update(ctx context.Context, in *DomainUpdateRequest, opts ...grpc.CallOption) (*DomainUpdateResponse, error)
Delete(ctx context.Context, in *DomainDeleteRequest, opts ...grpc.CallOption) (*DomainDeleteResponse, error)
Power(ctx context.Context, in *DomainPowerRequest, opts ...grpc.CallOption) (*DomainPowerResponse, error)
}
type domainClient struct {
cc grpc.ClientConnInterface
}
func NewDomainClient(cc grpc.ClientConnInterface) DomainClient {
return &domainClient{cc}
}
func (c *domainClient) List(ctx context.Context, in *DomainListAllRequest, opts ...grpc.CallOption) (*DomainListAllResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DomainListAllResponse)
err := c.cc.Invoke(ctx, Domain_List_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *domainClient) Get(ctx context.Context, in *DomainListRequest, opts ...grpc.CallOption) (*DomainListResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DomainListResponse)
err := c.cc.Invoke(ctx, Domain_Get_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *domainClient) Create(ctx context.Context, in *DomainCreateRequest, opts ...grpc.CallOption) (*DomainCreateResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DomainCreateResponse)
err := c.cc.Invoke(ctx, Domain_Create_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *domainClient) Update(ctx context.Context, in *DomainUpdateRequest, opts ...grpc.CallOption) (*DomainUpdateResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DomainUpdateResponse)
err := c.cc.Invoke(ctx, Domain_Update_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *domainClient) Delete(ctx context.Context, in *DomainDeleteRequest, opts ...grpc.CallOption) (*DomainDeleteResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DomainDeleteResponse)
err := c.cc.Invoke(ctx, Domain_Delete_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *domainClient) Power(ctx context.Context, in *DomainPowerRequest, opts ...grpc.CallOption) (*DomainPowerResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DomainPowerResponse)
err := c.cc.Invoke(ctx, Domain_Power_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// DomainServer is the server API for Domain service.
// All implementations must embed UnimplementedDomainServer
// for forward compatibility.
//
// The greeting service definition.
type DomainServer interface {
List(context.Context, *DomainListAllRequest) (*DomainListAllResponse, error)
Get(context.Context, *DomainListRequest) (*DomainListResponse, error)
Create(context.Context, *DomainCreateRequest) (*DomainCreateResponse, error)
Update(context.Context, *DomainUpdateRequest) (*DomainUpdateResponse, error)
Delete(context.Context, *DomainDeleteRequest) (*DomainDeleteResponse, error)
Power(context.Context, *DomainPowerRequest) (*DomainPowerResponse, error)
mustEmbedUnimplementedDomainServer()
}
// UnimplementedDomainServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedDomainServer struct{}
func (UnimplementedDomainServer) List(context.Context, *DomainListAllRequest) (*DomainListAllResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
}
func (UnimplementedDomainServer) Get(context.Context, *DomainListRequest) (*DomainListResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
}
func (UnimplementedDomainServer) Create(context.Context, *DomainCreateRequest) (*DomainCreateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Create not implemented")
}
func (UnimplementedDomainServer) Update(context.Context, *DomainUpdateRequest) (*DomainUpdateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Update not implemented")
}
func (UnimplementedDomainServer) Delete(context.Context, *DomainDeleteRequest) (*DomainDeleteResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
}
func (UnimplementedDomainServer) Power(context.Context, *DomainPowerRequest) (*DomainPowerResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Power not implemented")
}
func (UnimplementedDomainServer) mustEmbedUnimplementedDomainServer() {}
func (UnimplementedDomainServer) testEmbeddedByValue() {}
// UnsafeDomainServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to DomainServer will
// result in compilation errors.
type UnsafeDomainServer interface {
mustEmbedUnimplementedDomainServer()
}
func RegisterDomainServer(s grpc.ServiceRegistrar, srv DomainServer) {
// If the following call pancis, it indicates UnimplementedDomainServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&Domain_ServiceDesc, srv)
}
func _Domain_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DomainListAllRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainServer).List(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Domain_List_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainServer).List(ctx, req.(*DomainListAllRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Domain_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DomainListRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainServer).Get(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Domain_Get_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainServer).Get(ctx, req.(*DomainListRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Domain_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DomainCreateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainServer).Create(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Domain_Create_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainServer).Create(ctx, req.(*DomainCreateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Domain_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DomainUpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainServer).Update(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Domain_Update_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainServer).Update(ctx, req.(*DomainUpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Domain_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DomainDeleteRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainServer).Delete(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Domain_Delete_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainServer).Delete(ctx, req.(*DomainDeleteRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Domain_Power_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DomainPowerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainServer).Power(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Domain_Power_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainServer).Power(ctx, req.(*DomainPowerRequest))
}
return interceptor(ctx, in, info, handler)
}
// Domain_ServiceDesc is the grpc.ServiceDesc for Domain service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Domain_ServiceDesc = grpc.ServiceDesc{
ServiceName: "deevirt.Domain",
HandlerType: (*DomainServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "List",
Handler: _Domain_List_Handler,
},
{
MethodName: "Get",
Handler: _Domain_Get_Handler,
},
{
MethodName: "Create",
Handler: _Domain_Create_Handler,
},
{
MethodName: "Update",
Handler: _Domain_Update_Handler,
},
{
MethodName: "Delete",
Handler: _Domain_Delete_Handler,
},
{
MethodName: "Power",
Handler: _Domain_Power_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/domain.proto",
}
const (
DomainDevicesGraphics_Console_FullMethodName = "/deevirt.DomainDevicesGraphics/Console"
)
// DomainDevicesGraphicsClient is the client API for DomainDevicesGraphics service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type DomainDevicesGraphicsClient interface {
Console(ctx context.Context, in *DomainDevicesGraphicsConsoleRequest, opts ...grpc.CallOption) (*DomainDevicesGraphicsConsoleResponse, error)
}
type domainDevicesGraphicsClient struct {
cc grpc.ClientConnInterface
}
func NewDomainDevicesGraphicsClient(cc grpc.ClientConnInterface) DomainDevicesGraphicsClient {
return &domainDevicesGraphicsClient{cc}
}
func (c *domainDevicesGraphicsClient) Console(ctx context.Context, in *DomainDevicesGraphicsConsoleRequest, opts ...grpc.CallOption) (*DomainDevicesGraphicsConsoleResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DomainDevicesGraphicsConsoleResponse)
err := c.cc.Invoke(ctx, DomainDevicesGraphics_Console_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// DomainDevicesGraphicsServer is the server API for DomainDevicesGraphics service.
// All implementations must embed UnimplementedDomainDevicesGraphicsServer
// for forward compatibility.
type DomainDevicesGraphicsServer interface {
Console(context.Context, *DomainDevicesGraphicsConsoleRequest) (*DomainDevicesGraphicsConsoleResponse, error)
mustEmbedUnimplementedDomainDevicesGraphicsServer()
}
// UnimplementedDomainDevicesGraphicsServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedDomainDevicesGraphicsServer struct{}
func (UnimplementedDomainDevicesGraphicsServer) Console(context.Context, *DomainDevicesGraphicsConsoleRequest) (*DomainDevicesGraphicsConsoleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Console not implemented")
}
func (UnimplementedDomainDevicesGraphicsServer) mustEmbedUnimplementedDomainDevicesGraphicsServer() {}
func (UnimplementedDomainDevicesGraphicsServer) testEmbeddedByValue() {}
// UnsafeDomainDevicesGraphicsServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to DomainDevicesGraphicsServer will
// result in compilation errors.
type UnsafeDomainDevicesGraphicsServer interface {
mustEmbedUnimplementedDomainDevicesGraphicsServer()
}
func RegisterDomainDevicesGraphicsServer(s grpc.ServiceRegistrar, srv DomainDevicesGraphicsServer) {
// If the following call pancis, it indicates UnimplementedDomainDevicesGraphicsServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&DomainDevicesGraphics_ServiceDesc, srv)
}
func _DomainDevicesGraphics_Console_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DomainDevicesGraphicsConsoleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainDevicesGraphicsServer).Console(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: DomainDevicesGraphics_Console_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainDevicesGraphicsServer).Console(ctx, req.(*DomainDevicesGraphicsConsoleRequest))
}
return interceptor(ctx, in, info, handler)
}
// DomainDevicesGraphics_ServiceDesc is the grpc.ServiceDesc for DomainDevicesGraphics service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var DomainDevicesGraphics_ServiceDesc = grpc.ServiceDesc{
ServiceName: "deevirt.DomainDevicesGraphics",
HandlerType: (*DomainDevicesGraphicsServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Console",
Handler: _DomainDevicesGraphics_Console_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/domain.proto",
}

View File

@ -0,0 +1,62 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc v3.14.0
// source: proto/network.proto
package proto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
var File_proto_network_proto protoreflect.FileDescriptor
var file_proto_network_proto_rawDesc = []byte{
0x0a, 0x13, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x64, 0x65, 0x65, 0x76, 0x69, 0x72, 0x74, 0x42, 0x09,
0x5a, 0x07, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var file_proto_network_proto_goTypes = []interface{}{}
var file_proto_network_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_proto_network_proto_init() }
func file_proto_network_proto_init() {
if File_proto_network_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_network_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proto_network_proto_goTypes,
DependencyIndexes: file_proto_network_proto_depIdxs,
}.Build()
File_proto_network_proto = out.File
file_proto_network_proto_rawDesc = nil
file_proto_network_proto_goTypes = nil
file_proto_network_proto_depIdxs = nil
}

View File

@ -0,0 +1,4 @@
syntax="proto3";
option go_package = "./proto";
package deevirt;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,154 @@
syntax = "proto3";
option go_package = "./proto";
package raft;
service RaftAdmin {
rpc AddNonvoter(AddNonvoterRequest) returns (Future) {}
rpc AddVoter(AddVoterRequest) returns (Future) {}
rpc AppliedIndex(AppliedIndexRequest) returns (AppliedIndexResponse) {}
rpc ApplyLog(ApplyLogRequest) returns (Future) {}
rpc Barrier(BarrierRequest) returns (Future) {}
rpc DemoteVoter(DemoteVoterRequest) returns (Future) {}
rpc GetConfiguration(GetConfigurationRequest) returns (GetConfigurationResponse) {}
rpc LastContact(LastContactRequest) returns (LastContactResponse) {}
rpc LastIndex(LastIndexRequest) returns (LastIndexResponse) {}
rpc Leader(LeaderRequest) returns (LeaderResponse) {}
rpc LeadershipTransfer(LeadershipTransferRequest) returns (Future) {}
rpc LeadershipTransferToServer(LeadershipTransferToServerRequest) returns (Future) {}
rpc RemoveServer(RemoveServerRequest) returns (Future) {}
rpc Shutdown(ShutdownRequest) returns (Future) {}
rpc Snapshot(SnapshotRequest) returns (Future) {}
rpc State(StateRequest) returns (StateResponse) {}
rpc Stats(StatsRequest) returns (StatsResponse) {}
rpc VerifyLeader(VerifyLeaderRequest) returns (Future) {}
rpc Await(Future) returns (AwaitResponse) {}
rpc Forget(Future) returns (ForgetResponse) {}
}
message Future {
string operation_token = 1;
}
message AwaitResponse {
string error = 1;
uint64 index = 2;
}
message ForgetResponse {
}
message AddVoterRequest {
string id = 1;
string address = 2;
uint64 previous_index = 3;
}
message AddNonvoterRequest {
string id = 1;
string address = 2;
uint64 previous_index = 3;
}
message ApplyLogRequest {
bytes data = 1;
bytes extensions = 2;
}
message AppliedIndexRequest {
}
message AppliedIndexResponse {
uint64 index = 1;
}
message BarrierRequest {
}
message DemoteVoterRequest {
string id = 1;
uint64 previous_index = 2;
}
message GetConfigurationRequest {
}
message GetConfigurationResponse {
message Server {
enum Suffrage {
VOTER = 0;
NONVOTER = 1;
STAGING = 2;
}
Suffrage suffrage = 1;
string id = 2;
string address = 3;
}
repeated Server servers = 1;
}
message LastContactRequest {
}
message LastContactResponse {
int64 unix_nano = 1;
}
message LastIndexRequest {
}
message LastIndexResponse {
uint64 index = 1;
}
message LeaderRequest {
}
message LeaderResponse {
string address = 1;
}
message LeadershipTransferRequest {
}
message LeadershipTransferToServerRequest {
string id = 1;
string address = 2;
}
message RemoveServerRequest {
string id = 1;
uint64 previous_index = 2;
}
message ShutdownRequest {
}
message SnapshotRequest {
}
message StateRequest {
}
message StateResponse {
enum State {
FOLLOWER = 0;
CANDIDATE = 1;
LEADER = 2;
SHUTDOWN = 3;
}
State state = 1;
}
message StatsRequest {
}
message StatsResponse {
map<string, string> stats = 1;
}
message VerifyLeaderRequest {
}

View File

@ -0,0 +1,843 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v3.14.0
// source: proto/raft_admin.proto
package proto
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
RaftAdmin_AddNonvoter_FullMethodName = "/raft.RaftAdmin/AddNonvoter"
RaftAdmin_AddVoter_FullMethodName = "/raft.RaftAdmin/AddVoter"
RaftAdmin_AppliedIndex_FullMethodName = "/raft.RaftAdmin/AppliedIndex"
RaftAdmin_ApplyLog_FullMethodName = "/raft.RaftAdmin/ApplyLog"
RaftAdmin_Barrier_FullMethodName = "/raft.RaftAdmin/Barrier"
RaftAdmin_DemoteVoter_FullMethodName = "/raft.RaftAdmin/DemoteVoter"
RaftAdmin_GetConfiguration_FullMethodName = "/raft.RaftAdmin/GetConfiguration"
RaftAdmin_LastContact_FullMethodName = "/raft.RaftAdmin/LastContact"
RaftAdmin_LastIndex_FullMethodName = "/raft.RaftAdmin/LastIndex"
RaftAdmin_Leader_FullMethodName = "/raft.RaftAdmin/Leader"
RaftAdmin_LeadershipTransfer_FullMethodName = "/raft.RaftAdmin/LeadershipTransfer"
RaftAdmin_LeadershipTransferToServer_FullMethodName = "/raft.RaftAdmin/LeadershipTransferToServer"
RaftAdmin_RemoveServer_FullMethodName = "/raft.RaftAdmin/RemoveServer"
RaftAdmin_Shutdown_FullMethodName = "/raft.RaftAdmin/Shutdown"
RaftAdmin_Snapshot_FullMethodName = "/raft.RaftAdmin/Snapshot"
RaftAdmin_State_FullMethodName = "/raft.RaftAdmin/State"
RaftAdmin_Stats_FullMethodName = "/raft.RaftAdmin/Stats"
RaftAdmin_VerifyLeader_FullMethodName = "/raft.RaftAdmin/VerifyLeader"
RaftAdmin_Await_FullMethodName = "/raft.RaftAdmin/Await"
RaftAdmin_Forget_FullMethodName = "/raft.RaftAdmin/Forget"
)
// RaftAdminClient is the client API for RaftAdmin service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type RaftAdminClient interface {
AddNonvoter(ctx context.Context, in *AddNonvoterRequest, opts ...grpc.CallOption) (*Future, error)
AddVoter(ctx context.Context, in *AddVoterRequest, opts ...grpc.CallOption) (*Future, error)
AppliedIndex(ctx context.Context, in *AppliedIndexRequest, opts ...grpc.CallOption) (*AppliedIndexResponse, error)
ApplyLog(ctx context.Context, in *ApplyLogRequest, opts ...grpc.CallOption) (*Future, error)
Barrier(ctx context.Context, in *BarrierRequest, opts ...grpc.CallOption) (*Future, error)
DemoteVoter(ctx context.Context, in *DemoteVoterRequest, opts ...grpc.CallOption) (*Future, error)
GetConfiguration(ctx context.Context, in *GetConfigurationRequest, opts ...grpc.CallOption) (*GetConfigurationResponse, error)
LastContact(ctx context.Context, in *LastContactRequest, opts ...grpc.CallOption) (*LastContactResponse, error)
LastIndex(ctx context.Context, in *LastIndexRequest, opts ...grpc.CallOption) (*LastIndexResponse, error)
Leader(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (*LeaderResponse, error)
LeadershipTransfer(ctx context.Context, in *LeadershipTransferRequest, opts ...grpc.CallOption) (*Future, error)
LeadershipTransferToServer(ctx context.Context, in *LeadershipTransferToServerRequest, opts ...grpc.CallOption) (*Future, error)
RemoveServer(ctx context.Context, in *RemoveServerRequest, opts ...grpc.CallOption) (*Future, error)
Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Future, error)
Snapshot(ctx context.Context, in *SnapshotRequest, opts ...grpc.CallOption) (*Future, error)
State(ctx context.Context, in *StateRequest, opts ...grpc.CallOption) (*StateResponse, error)
Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error)
VerifyLeader(ctx context.Context, in *VerifyLeaderRequest, opts ...grpc.CallOption) (*Future, error)
Await(ctx context.Context, in *Future, opts ...grpc.CallOption) (*AwaitResponse, error)
Forget(ctx context.Context, in *Future, opts ...grpc.CallOption) (*ForgetResponse, error)
}
type raftAdminClient struct {
cc grpc.ClientConnInterface
}
func NewRaftAdminClient(cc grpc.ClientConnInterface) RaftAdminClient {
return &raftAdminClient{cc}
}
func (c *raftAdminClient) AddNonvoter(ctx context.Context, in *AddNonvoterRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_AddNonvoter_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) AddVoter(ctx context.Context, in *AddVoterRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_AddVoter_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) AppliedIndex(ctx context.Context, in *AppliedIndexRequest, opts ...grpc.CallOption) (*AppliedIndexResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AppliedIndexResponse)
err := c.cc.Invoke(ctx, RaftAdmin_AppliedIndex_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) ApplyLog(ctx context.Context, in *ApplyLogRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_ApplyLog_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) Barrier(ctx context.Context, in *BarrierRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_Barrier_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) DemoteVoter(ctx context.Context, in *DemoteVoterRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_DemoteVoter_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) GetConfiguration(ctx context.Context, in *GetConfigurationRequest, opts ...grpc.CallOption) (*GetConfigurationResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetConfigurationResponse)
err := c.cc.Invoke(ctx, RaftAdmin_GetConfiguration_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) LastContact(ctx context.Context, in *LastContactRequest, opts ...grpc.CallOption) (*LastContactResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(LastContactResponse)
err := c.cc.Invoke(ctx, RaftAdmin_LastContact_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) LastIndex(ctx context.Context, in *LastIndexRequest, opts ...grpc.CallOption) (*LastIndexResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(LastIndexResponse)
err := c.cc.Invoke(ctx, RaftAdmin_LastIndex_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) Leader(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (*LeaderResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(LeaderResponse)
err := c.cc.Invoke(ctx, RaftAdmin_Leader_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) LeadershipTransfer(ctx context.Context, in *LeadershipTransferRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_LeadershipTransfer_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) LeadershipTransferToServer(ctx context.Context, in *LeadershipTransferToServerRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_LeadershipTransferToServer_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) RemoveServer(ctx context.Context, in *RemoveServerRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_RemoveServer_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_Shutdown_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) Snapshot(ctx context.Context, in *SnapshotRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_Snapshot_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) State(ctx context.Context, in *StateRequest, opts ...grpc.CallOption) (*StateResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(StateResponse)
err := c.cc.Invoke(ctx, RaftAdmin_State_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(StatsResponse)
err := c.cc.Invoke(ctx, RaftAdmin_Stats_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) VerifyLeader(ctx context.Context, in *VerifyLeaderRequest, opts ...grpc.CallOption) (*Future, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Future)
err := c.cc.Invoke(ctx, RaftAdmin_VerifyLeader_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) Await(ctx context.Context, in *Future, opts ...grpc.CallOption) (*AwaitResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AwaitResponse)
err := c.cc.Invoke(ctx, RaftAdmin_Await_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *raftAdminClient) Forget(ctx context.Context, in *Future, opts ...grpc.CallOption) (*ForgetResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ForgetResponse)
err := c.cc.Invoke(ctx, RaftAdmin_Forget_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// RaftAdminServer is the server API for RaftAdmin service.
// All implementations must embed UnimplementedRaftAdminServer
// for forward compatibility.
type RaftAdminServer interface {
AddNonvoter(context.Context, *AddNonvoterRequest) (*Future, error)
AddVoter(context.Context, *AddVoterRequest) (*Future, error)
AppliedIndex(context.Context, *AppliedIndexRequest) (*AppliedIndexResponse, error)
ApplyLog(context.Context, *ApplyLogRequest) (*Future, error)
Barrier(context.Context, *BarrierRequest) (*Future, error)
DemoteVoter(context.Context, *DemoteVoterRequest) (*Future, error)
GetConfiguration(context.Context, *GetConfigurationRequest) (*GetConfigurationResponse, error)
LastContact(context.Context, *LastContactRequest) (*LastContactResponse, error)
LastIndex(context.Context, *LastIndexRequest) (*LastIndexResponse, error)
Leader(context.Context, *LeaderRequest) (*LeaderResponse, error)
LeadershipTransfer(context.Context, *LeadershipTransferRequest) (*Future, error)
LeadershipTransferToServer(context.Context, *LeadershipTransferToServerRequest) (*Future, error)
RemoveServer(context.Context, *RemoveServerRequest) (*Future, error)
Shutdown(context.Context, *ShutdownRequest) (*Future, error)
Snapshot(context.Context, *SnapshotRequest) (*Future, error)
State(context.Context, *StateRequest) (*StateResponse, error)
Stats(context.Context, *StatsRequest) (*StatsResponse, error)
VerifyLeader(context.Context, *VerifyLeaderRequest) (*Future, error)
Await(context.Context, *Future) (*AwaitResponse, error)
Forget(context.Context, *Future) (*ForgetResponse, error)
mustEmbedUnimplementedRaftAdminServer()
}
// UnimplementedRaftAdminServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedRaftAdminServer struct{}
func (UnimplementedRaftAdminServer) AddNonvoter(context.Context, *AddNonvoterRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddNonvoter not implemented")
}
func (UnimplementedRaftAdminServer) AddVoter(context.Context, *AddVoterRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddVoter not implemented")
}
func (UnimplementedRaftAdminServer) AppliedIndex(context.Context, *AppliedIndexRequest) (*AppliedIndexResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AppliedIndex not implemented")
}
func (UnimplementedRaftAdminServer) ApplyLog(context.Context, *ApplyLogRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method ApplyLog not implemented")
}
func (UnimplementedRaftAdminServer) Barrier(context.Context, *BarrierRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method Barrier not implemented")
}
func (UnimplementedRaftAdminServer) DemoteVoter(context.Context, *DemoteVoterRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method DemoteVoter not implemented")
}
func (UnimplementedRaftAdminServer) GetConfiguration(context.Context, *GetConfigurationRequest) (*GetConfigurationResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetConfiguration not implemented")
}
func (UnimplementedRaftAdminServer) LastContact(context.Context, *LastContactRequest) (*LastContactResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method LastContact not implemented")
}
func (UnimplementedRaftAdminServer) LastIndex(context.Context, *LastIndexRequest) (*LastIndexResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method LastIndex not implemented")
}
func (UnimplementedRaftAdminServer) Leader(context.Context, *LeaderRequest) (*LeaderResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Leader not implemented")
}
func (UnimplementedRaftAdminServer) LeadershipTransfer(context.Context, *LeadershipTransferRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method LeadershipTransfer not implemented")
}
func (UnimplementedRaftAdminServer) LeadershipTransferToServer(context.Context, *LeadershipTransferToServerRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method LeadershipTransferToServer not implemented")
}
func (UnimplementedRaftAdminServer) RemoveServer(context.Context, *RemoveServerRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method RemoveServer not implemented")
}
func (UnimplementedRaftAdminServer) Shutdown(context.Context, *ShutdownRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method Shutdown not implemented")
}
func (UnimplementedRaftAdminServer) Snapshot(context.Context, *SnapshotRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method Snapshot not implemented")
}
func (UnimplementedRaftAdminServer) State(context.Context, *StateRequest) (*StateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method State not implemented")
}
func (UnimplementedRaftAdminServer) Stats(context.Context, *StatsRequest) (*StatsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Stats not implemented")
}
func (UnimplementedRaftAdminServer) VerifyLeader(context.Context, *VerifyLeaderRequest) (*Future, error) {
return nil, status.Errorf(codes.Unimplemented, "method VerifyLeader not implemented")
}
func (UnimplementedRaftAdminServer) Await(context.Context, *Future) (*AwaitResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Await not implemented")
}
func (UnimplementedRaftAdminServer) Forget(context.Context, *Future) (*ForgetResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Forget not implemented")
}
func (UnimplementedRaftAdminServer) mustEmbedUnimplementedRaftAdminServer() {}
func (UnimplementedRaftAdminServer) testEmbeddedByValue() {}
// UnsafeRaftAdminServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to RaftAdminServer will
// result in compilation errors.
type UnsafeRaftAdminServer interface {
mustEmbedUnimplementedRaftAdminServer()
}
func RegisterRaftAdminServer(s grpc.ServiceRegistrar, srv RaftAdminServer) {
// If the following call pancis, it indicates UnimplementedRaftAdminServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&RaftAdmin_ServiceDesc, srv)
}
func _RaftAdmin_AddNonvoter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddNonvoterRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).AddNonvoter(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_AddNonvoter_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).AddNonvoter(ctx, req.(*AddNonvoterRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_AddVoter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddVoterRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).AddVoter(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_AddVoter_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).AddVoter(ctx, req.(*AddVoterRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_AppliedIndex_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AppliedIndexRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).AppliedIndex(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_AppliedIndex_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).AppliedIndex(ctx, req.(*AppliedIndexRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_ApplyLog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ApplyLogRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).ApplyLog(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_ApplyLog_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).ApplyLog(ctx, req.(*ApplyLogRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_Barrier_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BarrierRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).Barrier(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_Barrier_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).Barrier(ctx, req.(*BarrierRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_DemoteVoter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DemoteVoterRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).DemoteVoter(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_DemoteVoter_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).DemoteVoter(ctx, req.(*DemoteVoterRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_GetConfiguration_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetConfigurationRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).GetConfiguration(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_GetConfiguration_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).GetConfiguration(ctx, req.(*GetConfigurationRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_LastContact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LastContactRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).LastContact(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_LastContact_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).LastContact(ctx, req.(*LastContactRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_LastIndex_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LastIndexRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).LastIndex(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_LastIndex_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).LastIndex(ctx, req.(*LastIndexRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_Leader_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LeaderRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).Leader(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_Leader_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).Leader(ctx, req.(*LeaderRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_LeadershipTransfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LeadershipTransferRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).LeadershipTransfer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_LeadershipTransfer_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).LeadershipTransfer(ctx, req.(*LeadershipTransferRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_LeadershipTransferToServer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LeadershipTransferToServerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).LeadershipTransferToServer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_LeadershipTransferToServer_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).LeadershipTransferToServer(ctx, req.(*LeadershipTransferToServerRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_RemoveServer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RemoveServerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).RemoveServer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_RemoveServer_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).RemoveServer(ctx, req.(*RemoveServerRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ShutdownRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).Shutdown(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_Shutdown_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).Shutdown(ctx, req.(*ShutdownRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_Snapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SnapshotRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).Snapshot(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_Snapshot_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).Snapshot(ctx, req.(*SnapshotRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_State_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).State(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_State_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).State(ctx, req.(*StateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_Stats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StatsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).Stats(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_Stats_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).Stats(ctx, req.(*StatsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_VerifyLeader_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(VerifyLeaderRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).VerifyLeader(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_VerifyLeader_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).VerifyLeader(ctx, req.(*VerifyLeaderRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_Await_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Future)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).Await(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_Await_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).Await(ctx, req.(*Future))
}
return interceptor(ctx, in, info, handler)
}
func _RaftAdmin_Forget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Future)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RaftAdminServer).Forget(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RaftAdmin_Forget_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RaftAdminServer).Forget(ctx, req.(*Future))
}
return interceptor(ctx, in, info, handler)
}
// RaftAdmin_ServiceDesc is the grpc.ServiceDesc for RaftAdmin service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var RaftAdmin_ServiceDesc = grpc.ServiceDesc{
ServiceName: "raft.RaftAdmin",
HandlerType: (*RaftAdminServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "AddNonvoter",
Handler: _RaftAdmin_AddNonvoter_Handler,
},
{
MethodName: "AddVoter",
Handler: _RaftAdmin_AddVoter_Handler,
},
{
MethodName: "AppliedIndex",
Handler: _RaftAdmin_AppliedIndex_Handler,
},
{
MethodName: "ApplyLog",
Handler: _RaftAdmin_ApplyLog_Handler,
},
{
MethodName: "Barrier",
Handler: _RaftAdmin_Barrier_Handler,
},
{
MethodName: "DemoteVoter",
Handler: _RaftAdmin_DemoteVoter_Handler,
},
{
MethodName: "GetConfiguration",
Handler: _RaftAdmin_GetConfiguration_Handler,
},
{
MethodName: "LastContact",
Handler: _RaftAdmin_LastContact_Handler,
},
{
MethodName: "LastIndex",
Handler: _RaftAdmin_LastIndex_Handler,
},
{
MethodName: "Leader",
Handler: _RaftAdmin_Leader_Handler,
},
{
MethodName: "LeadershipTransfer",
Handler: _RaftAdmin_LeadershipTransfer_Handler,
},
{
MethodName: "LeadershipTransferToServer",
Handler: _RaftAdmin_LeadershipTransferToServer_Handler,
},
{
MethodName: "RemoveServer",
Handler: _RaftAdmin_RemoveServer_Handler,
},
{
MethodName: "Shutdown",
Handler: _RaftAdmin_Shutdown_Handler,
},
{
MethodName: "Snapshot",
Handler: _RaftAdmin_Snapshot_Handler,
},
{
MethodName: "State",
Handler: _RaftAdmin_State_Handler,
},
{
MethodName: "Stats",
Handler: _RaftAdmin_Stats_Handler,
},
{
MethodName: "VerifyLeader",
Handler: _RaftAdmin_VerifyLeader_Handler,
},
{
MethodName: "Await",
Handler: _RaftAdmin_Await_Handler,
},
{
MethodName: "Forget",
Handler: _RaftAdmin_Forget_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/raft_admin.proto",
}

View File

@ -0,0 +1,62 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc v3.14.0
// source: proto/storage.proto
package proto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
var File_proto_storage_proto protoreflect.FileDescriptor
var file_proto_storage_proto_rawDesc = []byte{
0x0a, 0x13, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x64, 0x65, 0x65, 0x76, 0x69, 0x72, 0x74, 0x42, 0x09,
0x5a, 0x07, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var file_proto_storage_proto_goTypes = []interface{}{}
var file_proto_storage_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_proto_storage_proto_init() }
func file_proto_storage_proto_init() {
if File_proto_storage_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_storage_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proto_storage_proto_goTypes,
DependencyIndexes: file_proto_storage_proto_depIdxs,
}.Build()
File_proto_storage_proto = out.File
file_proto_storage_proto_rawDesc = nil
file_proto_storage_proto_goTypes = nil
file_proto_storage_proto_depIdxs = nil
}

View File

@ -0,0 +1,4 @@
syntax="proto3";
option go_package = "./proto";
package deevirt;

38
pkg/api/server.go Normal file
View File

@ -0,0 +1,38 @@
package api
import (
"context"
"fmt"
"log"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
pb "deevirt.fr/compute/pkg/api/proto"
"deevirt.fr/compute/pkg/raft"
)
func Server() {
ctx := context.Background()
sock, err := net.Listen("tcp", fmt.Sprintf(":%d", 4480))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
r, tm, err := raft.New(ctx, 4480)
if err != nil {
log.Fatalf("failed to start raft: %v", err)
}
s := grpc.NewServer()
pb.RegisterDomainServer(s, nil)
tm.Register(s)
//leaderhealth.Setup(r, s, []string{"Example"})
raft.Register(s, r)
reflection.Register(s)
if err := s.Serve(sock); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}

View File

@ -4,20 +4,32 @@ import (
"encoding/hex"
"fmt"
"log"
"strings"
"github.com/denisbrodbeck/machineid"
"gopkg.in/ini.v1"
)
type Config struct {
ClusterID string
NodeID string
ClusterID string
AddressPublic string
AddressPrivate string
NodeID string
Manager Manager
AmqpURI string
EtcdURI string
LibvirtTLS bool
}
func NewConfig() (*Config, error) {
type Manager struct {
Peers []string
TlsKey string
TlsCert string
TlsCA string
}
func New() (*Config, error) {
c, err := ini.Load("/etc/deevirt/config.ini")
if err != nil {
log.Fatal(err)
@ -31,9 +43,20 @@ func NewConfig() (*Config, error) {
mID, _ := hex.DecodeString(id)
libvirtTLS, _ := c.Section("libvirt").Key("tls").Bool()
//Manager
peers := strings.Split(c.Section("mgr").Key("peers").String(), ",")
manager := &Manager{
Peers: peers,
}
return &Config{
ClusterID: c.Section("").Key("id").String(),
NodeID: fmt.Sprintf("%x-%x-%x-%x-%x", mID[:4], mID[4:6], mID[6:8], mID[8:10], mID[10:]),
ClusterID: c.Section("").Key("id_cluster").String(),
AddressPublic: c.Section("").Key("ip_public").String(),
AddressPrivate: c.Section("").Key("ip_private").String(),
NodeID: fmt.Sprintf("%x-%x-%x-%x-%x", mID[:4], mID[4:6], mID[6:8], mID[8:10], mID[10:]),
Manager: *manager,
AmqpURI: c.Section("broker").Key("uri").String(),
EtcdURI: c.Section("etcd").Key("uri").String(),
LibvirtTLS: libvirtTLS,

43
pkg/etcd/client.go Normal file
View File

@ -0,0 +1,43 @@
package etcd
import (
"context"
"encoding/json"
"log"
"strings"
"time"
clientv3 "go.etcd.io/etcd/client/v3"
)
type Node struct {
IpManagement string `json:"ip_mgmt"`
}
func New(uri string) (*clientv3.Client, error) {
etcd, err := clientv3.New(clientv3.Config{
Endpoints: strings.Split(uri, ","),
DialTimeout: 5 * time.Second,
})
if err != nil {
log.Fatalf("Error connexion to etcd: %v", err)
}
return etcd, nil
}
func GetNodes(c *clientv3.Client, cluster_id string) map[string]Node {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
resp, _ := c.Get(ctx, "/cluster/"+cluster_id)
var nodes map[string]Node
err := json.Unmarshal(resp.Kvs[0].Value, &nodes)
if err != nil {
log.Fatal("Erreur lors du parsing du JSON: ", err)
}
return nodes
}

198
pkg/raft/admin.go Normal file
View File

@ -0,0 +1,198 @@
package raft
import (
"context"
"crypto/sha1"
"fmt"
"math/rand"
"sync"
"time"
pb "deevirt.fr/compute/pkg/api/proto"
"github.com/hashicorp/raft"
"google.golang.org/grpc"
)
type admin struct {
r *raft.Raft
pb.UnimplementedRaftAdminServer
}
func Register(s *grpc.Server, r *raft.Raft) {
pb.RegisterRaftAdminServer(s, &admin{r: r})
}
func timeout(ctx context.Context) time.Duration {
if dl, ok := ctx.Deadline(); ok {
return time.Until(dl)
}
return 0
}
var (
mtx sync.Mutex
operations = map[string]*future{}
)
type future struct {
f raft.Future
mtx sync.Mutex
}
func toFuture(f raft.Future) (*pb.Future, error) {
token := fmt.Sprintf("%x", sha1.Sum([]byte(fmt.Sprintf("%d", rand.Uint64()))))
mtx.Lock()
operations[token] = &future{f: f}
mtx.Unlock()
return &pb.Future{
OperationToken: token,
}, nil
}
func (a *admin) Await(ctx context.Context, req *pb.Future) (*pb.AwaitResponse, error) {
mtx.Lock()
f, ok := operations[req.GetOperationToken()]
mtx.Unlock()
if !ok {
return nil, fmt.Errorf("token %q unknown", req.GetOperationToken())
}
f.mtx.Lock()
err := f.f.Error()
f.mtx.Unlock()
if err != nil {
return &pb.AwaitResponse{
Error: err.Error(),
}, nil
}
r := &pb.AwaitResponse{}
if ifx, ok := f.f.(raft.IndexFuture); ok {
r.Index = ifx.Index()
}
return r, nil
}
func (a *admin) Forget(ctx context.Context, req *pb.Future) (*pb.ForgetResponse, error) {
mtx.Lock()
delete(operations, req.GetOperationToken())
mtx.Unlock()
return &pb.ForgetResponse{}, nil
}
func (a *admin) AddNonvoter(ctx context.Context, req *pb.AddNonvoterRequest) (*pb.Future, error) {
return toFuture(a.r.AddNonvoter(raft.ServerID(req.GetId()), raft.ServerAddress(req.GetAddress()), req.GetPreviousIndex(), timeout(ctx)))
}
func (a *admin) AddVoter(ctx context.Context, req *pb.AddVoterRequest) (*pb.Future, error) {
return toFuture(a.r.AddVoter(raft.ServerID(req.GetId()), raft.ServerAddress(req.GetAddress()), req.GetPreviousIndex(), timeout(ctx)))
}
func (a *admin) AppliedIndex(ctx context.Context, req *pb.AppliedIndexRequest) (*pb.AppliedIndexResponse, error) {
return &pb.AppliedIndexResponse{
Index: a.r.AppliedIndex(),
}, nil
}
func (a *admin) ApplyLog(ctx context.Context, req *pb.ApplyLogRequest) (*pb.Future, error) {
return toFuture(a.r.ApplyLog(raft.Log{Data: req.GetData(), Extensions: req.GetExtensions()}, timeout(ctx)))
}
func (a *admin) Barrier(ctx context.Context, req *pb.BarrierRequest) (*pb.Future, error) {
return toFuture(a.r.Barrier(timeout(ctx)))
}
func (a *admin) DemoteVoter(ctx context.Context, req *pb.DemoteVoterRequest) (*pb.Future, error) {
return toFuture(a.r.DemoteVoter(raft.ServerID(req.GetId()), req.GetPreviousIndex(), timeout(ctx)))
}
func (a *admin) GetConfiguration(ctx context.Context, req *pb.GetConfigurationRequest) (*pb.GetConfigurationResponse, error) {
f := a.r.GetConfiguration()
if err := f.Error(); err != nil {
return nil, err
}
resp := &pb.GetConfigurationResponse{}
for _, s := range f.Configuration().Servers {
cs := &pb.GetConfigurationResponse_Server{
Id: string(s.ID),
Address: string(s.Address),
}
switch s.Suffrage {
case raft.Voter:
cs.Suffrage = pb.GetConfigurationResponse_Server_VOTER
case raft.Nonvoter:
cs.Suffrage = pb.GetConfigurationResponse_Server_NONVOTER
case raft.Staging:
cs.Suffrage = pb.GetConfigurationResponse_Server_STAGING
default:
return nil, fmt.Errorf("unknown server suffrage %v for server %q", s.Suffrage, s.ID)
}
resp.Servers = append(resp.Servers, cs)
}
return resp, nil
}
func (a *admin) LastContact(ctx context.Context, req *pb.LastContactRequest) (*pb.LastContactResponse, error) {
t := a.r.LastContact()
return &pb.LastContactResponse{
UnixNano: t.UnixNano(),
}, nil
}
func (a *admin) LastIndex(ctx context.Context, req *pb.LastIndexRequest) (*pb.LastIndexResponse, error) {
return &pb.LastIndexResponse{
Index: a.r.LastIndex(),
}, nil
}
func (a *admin) Leader(ctx context.Context, req *pb.LeaderRequest) (*pb.LeaderResponse, error) {
return &pb.LeaderResponse{
Address: string(a.r.Leader()),
}, nil
}
func (a *admin) LeadershipTransfer(ctx context.Context, req *pb.LeadershipTransferRequest) (*pb.Future, error) {
return toFuture(a.r.LeadershipTransfer())
}
func (a *admin) LeadershipTransferToServer(ctx context.Context, req *pb.LeadershipTransferToServerRequest) (*pb.Future, error) {
return toFuture(a.r.LeadershipTransferToServer(raft.ServerID(req.GetId()), raft.ServerAddress(req.GetAddress())))
}
func (a *admin) RemoveServer(ctx context.Context, req *pb.RemoveServerRequest) (*pb.Future, error) {
return toFuture(a.r.RemoveServer(raft.ServerID(req.GetId()), req.GetPreviousIndex(), timeout(ctx)))
}
func (a *admin) Shutdown(ctx context.Context, req *pb.ShutdownRequest) (*pb.Future, error) {
return toFuture(a.r.Shutdown())
}
func (a *admin) Snapshot(ctx context.Context, req *pb.SnapshotRequest) (*pb.Future, error) {
return toFuture(a.r.Snapshot())
}
func (a *admin) State(ctx context.Context, req *pb.StateRequest) (*pb.StateResponse, error) {
switch s := a.r.State(); s {
case raft.Follower:
return &pb.StateResponse{State: pb.StateResponse_FOLLOWER}, nil
case raft.Candidate:
return &pb.StateResponse{State: pb.StateResponse_CANDIDATE}, nil
case raft.Leader:
return &pb.StateResponse{State: pb.StateResponse_LEADER}, nil
case raft.Shutdown:
return &pb.StateResponse{State: pb.StateResponse_SHUTDOWN}, nil
default:
return nil, fmt.Errorf("unknown raft state %v", s)
}
}
func (a *admin) Stats(ctx context.Context, req *pb.StatsRequest) (*pb.StatsResponse, error) {
ret := &pb.StatsResponse{}
ret.Stats = map[string]string{}
for k, v := range a.r.Stats() {
ret.Stats[k] = v
}
return ret, nil
}
func (a *admin) VerifyLeader(ctx context.Context, req *pb.VerifyLeaderRequest) (*pb.Future, error) {
return toFuture(a.r.VerifyLeader())
}

185
pkg/raft/node.go Normal file
View File

@ -0,0 +1,185 @@
package raft
import (
"context"
"fmt"
"log"
"os"
"path/filepath"
transport "github.com/Jille/raft-grpc-transport"
"github.com/hashicorp/raft"
raftboltdb "github.com/hashicorp/raft-boltdb"
"google.golang.org/grpc"
"deevirt.fr/compute/pkg/config"
etcd_client "deevirt.fr/compute/pkg/etcd"
"deevirt.fr/compute/pkg/scheduler"
)
type RaftNode struct {
Raft *raft.Raft
NodeID string
StateCh chan raft.Observation
scheduler *scheduler.Scheduler
}
type Peers struct {
Id string
Address string
}
func New(ctx context.Context, port int) (*raft.Raft, *transport.Manager, error) {
// Récupération de la configuration deevirt
conf, err := config.New()
if err != nil {
return nil, nil, err
}
// Création du répertoire
baseDir := filepath.Join("/var/lib/deevirt/mgr/", conf.NodeID)
err = os.MkdirAll(baseDir, 0740)
if err != nil {
return nil, nil, err
}
// Récupération des Noeuds ID
etcd, err := etcd_client.New(conf.EtcdURI)
if err != nil {
return nil, nil, err
}
defer etcd.Close()
peers := []raft.Server{}
for key, value := range etcd_client.GetNodes(etcd, conf.ClusterID) {
var p string
for _, peer := range conf.Manager.Peers {
if peer == value.IpManagement {
p = peer
}
}
if p != "" {
peers = append(peers, raft.Server{
ID: raft.ServerID(key),
Address: raft.ServerAddress(fmt.Sprintf("%s:%d", p, port)),
})
}
}
c := raft.DefaultConfig()
c.LocalID = raft.ServerID(conf.NodeID)
ldb, err := raftboltdb.NewBoltStore(filepath.Join(baseDir, "logs.dat"))
if err != nil {
return nil, nil, fmt.Errorf(`boltdb.NewBoltStore(%q): %v`, filepath.Join(baseDir, "logs.dat"), err)
}
sdb, err := raftboltdb.NewBoltStore(filepath.Join(baseDir, "stable.dat"))
if err != nil {
return nil, nil, fmt.Errorf(`boltdb.NewBoltStore(%q): %v`, filepath.Join(baseDir, "stable.dat"), err)
}
fss, err := raft.NewFileSnapshotStore(baseDir, 3, os.Stderr)
if err != nil {
return nil, nil, fmt.Errorf(`raft.NewFileSnapshotStore(%q, ...): %v`, baseDir, err)
}
tm := transport.New(raft.ServerAddress(fmt.Sprintf("%s:%d", conf.AddressPrivate, port)), []grpc.DialOption{grpc.WithInsecure()})
r, err := raft.NewRaft(c, nil, ldb, sdb, fss, tm.Transport())
if err != nil {
return nil, nil, fmt.Errorf("raft.NewRaft: %v", err)
}
s, err := scheduler.New()
if err != nil {
return nil, nil, fmt.Errorf("scheduler: %v", err)
}
// Observer pour surveiller les changements d'état
stateCh := make(chan raft.Observation, 1) // Canal de type raft.Observation
r.RegisterObserver(raft.NewObserver(stateCh, true, nil))
node := &RaftNode{
Raft: r,
NodeID: conf.NodeID,
StateCh: stateCh,
scheduler: s,
}
go node.watchStateChanges()
hasState, _ := checkIfStateExists(ldb)
if conf.Manager.Peers[0] == conf.AddressPrivate && !hasState {
println("Démarrage du bootstrap ! ")
cfg := raft.Configuration{
Servers: peers,
}
f := r.BootstrapCluster(cfg)
if err := f.Error(); err != nil {
return nil, nil, fmt.Errorf("raft.Raft.BootstrapCluster: %v", err)
}
}
return r, tm, nil
}
// Vérifie si l'état Raft existe déjà
func checkIfStateExists(logStore *raftboltdb.BoltStore) (bool, error) {
// Vérifier les logs Raft
firstIndex, err := logStore.FirstIndex()
if err != nil {
return false, err
}
if firstIndex > 0 {
return true, nil
}
return false, nil
}
// Fonction pour surveiller et afficher les changements d'état
func (n *RaftNode) watchStateChanges() {
for obs := range n.StateCh {
switch evt := obs.Data.(type) {
case raft.RaftState:
if evt == raft.Leader {
go n.scheduler.Start()
log.Println("[ÉVÉNEMENT] Changement d'état Raft :", evt)
} else {
n.scheduler.Stop()
}
log.Println("[ÉVÉNEMENT] Changement d'état Raft :", evt)
case raft.LeaderObservation:
log.Println("[ÉVÉNEMENT] Le leader est", evt.LeaderID)
case raft.PeerObservation:
if n.Raft.State() == raft.Leader {
peerID := evt.Peer.ID
peerAddr := evt.Peer.Address
log.Println("[NOUVEAU NŒUD] Détection de", peerID, "à", peerAddr)
log.Println("[ACTION] Ajout automatique en tant que voter...")
future := n.Raft.AddVoter(peerID, peerAddr, 0, 0)
if err := future.Error(); err != nil {
log.Println("[ERREUR] Impossible d'ajouter", peerID, ":", err)
} else {
log.Println("[SUCCÈS] Voter ajouté :", peerID)
}
}
case raft.FailedHeartbeatObservation:
log.Println("[ÉVÉNEMENT] Perte de connexion avec un nœud :", evt.PeerID)
default:
log.Println("[ÉVÉNEMENT] Autre événement :", evt)
}
}
}

41
pkg/raft/worker.go Normal file
View File

@ -0,0 +1,41 @@
package raft
import (
"context"
"fmt"
"time"
)
type Worker struct {
ctx context.Context
cancel context.CancelFunc
cancelled bool // Variable pour suivre si cancel a été appelé
}
func (w *Worker) Start() {
go func() {
for {
select {
case <-w.ctx.Done():
fmt.Println("🛑 Worker arrêté !")
return
default:
fmt.Println("🔄 Worker en cours...")
time.Sleep(1 * time.Second)
}
}
}()
}
func (w *Worker) Stop() {
if !w.cancelled {
w.cancel() // Annuler le contexte
w.cancelled = true // Marquer comme annulé
} else {
fmt.Println("❗ Cancel déjà appelé, Worker déjà arrêté.")
}
}
func (w *Worker) IsCancelled() bool {
return w.cancelled
}

View File

@ -22,7 +22,7 @@ type Scheduler struct {
}
func New() (*Scheduler, error) {
config, _ := config.NewConfig()
config, _ := config.New()
ctx, cancel := context.WithCancel(context.Background())
logger, _ := zap.NewProduction()