WatchDog Kube
This commit is contained in:
174
infrastructure/storage/pvc_setter.go
Normal file
174
infrastructure/storage/pvc_setter.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"oc-datacenter/conf"
|
||||
|
||||
oclib "cloud.o-forge.io/core/oc-lib"
|
||||
"cloud.o-forge.io/core/oc-lib/models/live"
|
||||
"cloud.o-forge.io/core/oc-lib/tools"
|
||||
)
|
||||
|
||||
// PVCProvisionEvent is the NATS payload for local PVC provisioning.
|
||||
// Same-peer deployments are handled directly; cross-peer routes via PB_PVC_CONFIG.
|
||||
type PVCProvisionEvent struct {
|
||||
ExecutionsID string `json:"executions_id"`
|
||||
StorageID string `json:"storage_id"`
|
||||
StorageName string `json:"storage_name"`
|
||||
SourcePeerID string `json:"source_peer_id"`
|
||||
DestPeerID string `json:"dest_peer_id"`
|
||||
OriginID string `json:"origin_id"`
|
||||
}
|
||||
|
||||
// PVCDeleteEvent is the NATS payload for local PVC teardown.
|
||||
type PVCDeleteEvent struct {
|
||||
ExecutionsID string `json:"executions_id"`
|
||||
StorageID string `json:"storage_id"`
|
||||
StorageName string `json:"storage_name"`
|
||||
SourcePeerID string `json:"source_peer_id"`
|
||||
DestPeerID string `json:"dest_peer_id"`
|
||||
OriginID string `json:"origin_id"`
|
||||
}
|
||||
|
||||
// ClaimName returns the deterministic PVC name shared by oc-datacenter and oc-monitord.
|
||||
func ClaimName(storageName, executionsID string) string {
|
||||
return strings.ReplaceAll(strings.ToLower(storageName), " ", "-") + "-" + executionsID
|
||||
}
|
||||
|
||||
// PVCSetter carries the execution context for a local PVC provisioning.
|
||||
type PVCSetter struct {
|
||||
ExecutionsID string
|
||||
StorageID string
|
||||
}
|
||||
|
||||
func NewPVCSetter(execID, storageID string) *PVCSetter {
|
||||
return &PVCSetter{ExecutionsID: execID, StorageID: storageID}
|
||||
}
|
||||
|
||||
func emitConsiders(executionsID, originID string, provErr error, self bool) {
|
||||
type pvcConsidersPayload struct {
|
||||
OriginID string `json:"origin_id"`
|
||||
ExecutionsID string `json:"executions_id"`
|
||||
Error *string `json:"error,omitempty"`
|
||||
}
|
||||
var errStr *string
|
||||
if provErr != nil {
|
||||
s := provErr.Error()
|
||||
errStr = &s
|
||||
}
|
||||
payload, _ := json.Marshal(pvcConsidersPayload{
|
||||
OriginID: originID,
|
||||
ExecutionsID: executionsID,
|
||||
Error: errStr,
|
||||
})
|
||||
if self {
|
||||
go tools.NewNATSCaller().SetNATSPub(tools.CONSIDERS_EVENT, tools.NATSResponse{
|
||||
FromApp: "oc-datacenter",
|
||||
Datatype: tools.STORAGE_RESOURCE,
|
||||
Method: int(tools.CONSIDERS_EVENT),
|
||||
Payload: payload,
|
||||
})
|
||||
return
|
||||
}
|
||||
b, _ := json.Marshal(&tools.PropalgationMessage{
|
||||
DataType: tools.STORAGE_RESOURCE.EnumIndex(),
|
||||
Action: tools.PB_CONSIDERS,
|
||||
Payload: payload,
|
||||
})
|
||||
go tools.NewNATSCaller().SetNATSPub(tools.PROPALGATION_EVENT, tools.NATSResponse{
|
||||
FromApp: "oc-datacenter",
|
||||
Datatype: -1,
|
||||
Method: int(tools.PROPALGATION_EVENT),
|
||||
Payload: b,
|
||||
})
|
||||
}
|
||||
|
||||
// InitializeAsSource creates the PVC in the execution namespace on the local cluster.
|
||||
// self must be true when source and dest are the same peer (direct CONSIDERS_EVENT emission).
|
||||
func (p *PVCSetter) InitializeAsSource(ctx context.Context, event PVCProvisionEvent, self bool) {
|
||||
logger := oclib.GetLogger()
|
||||
|
||||
sizeStr, err := p.loadStorageSize(event.SourcePeerID)
|
||||
if err != nil {
|
||||
logger.Error().Msg("PVCSetter.InitializeAsSource: " + err.Error())
|
||||
emitConsiders(event.ExecutionsID, event.OriginID, err, self)
|
||||
return
|
||||
}
|
||||
|
||||
k, err := tools.NewKubernetesService(
|
||||
conf.GetConfig().KubeHost+":"+conf.GetConfig().KubePort,
|
||||
conf.GetConfig().KubeCA, conf.GetConfig().KubeCert, conf.GetConfig().KubeData,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error().Msg("PVCSetter.InitializeAsSource: failed to create k8s service: " + err.Error())
|
||||
emitConsiders(event.ExecutionsID, event.OriginID, err, self)
|
||||
return
|
||||
}
|
||||
|
||||
claimName := ClaimName(event.StorageName, event.ExecutionsID)
|
||||
if err := k.CreatePVC(ctx, claimName, event.ExecutionsID, sizeStr); err != nil {
|
||||
logger.Error().Msg("PVCSetter.InitializeAsSource: failed to create PVC: " + err.Error())
|
||||
emitConsiders(event.ExecutionsID, event.OriginID, err, self)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info().Msg("PVCSetter.InitializeAsSource: PVC " + claimName + " created in " + event.ExecutionsID)
|
||||
emitConsiders(event.ExecutionsID, event.OriginID, nil, self)
|
||||
}
|
||||
|
||||
// TeardownAsSource deletes the PVC from the execution namespace.
|
||||
func (p *PVCSetter) TeardownAsSource(ctx context.Context, event PVCDeleteEvent) {
|
||||
logger := oclib.GetLogger()
|
||||
|
||||
k, err := tools.NewKubernetesService(
|
||||
conf.GetConfig().KubeHost+":"+conf.GetConfig().KubePort,
|
||||
conf.GetConfig().KubeCA, conf.GetConfig().KubeCert, conf.GetConfig().KubeData,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error().Msg("PVCSetter.TeardownAsSource: failed to create k8s service: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
claimName := ClaimName(event.StorageName, event.ExecutionsID)
|
||||
if err := k.DeletePVC(ctx, claimName, event.ExecutionsID); err != nil {
|
||||
logger.Error().Msg("PVCSetter.TeardownAsSource: failed to delete PVC: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info().Msg("PVCSetter.TeardownAsSource: PVC " + claimName + " deleted from " + event.ExecutionsID)
|
||||
}
|
||||
|
||||
// ResolveStorageName returns the live storage name for a given storageID, or "" if not found.
|
||||
func ResolveStorageName(storageID, peerID string) string {
|
||||
res := oclib.NewRequest(oclib.LibDataEnum(oclib.LIVE_STORAGE), "", peerID, []string{}, nil).LoadAll(false)
|
||||
if res.Err != "" {
|
||||
return ""
|
||||
}
|
||||
for _, dbo := range res.Data {
|
||||
l := dbo.(*live.LiveStorage)
|
||||
if slices.Contains(l.ResourcesID, storageID) {
|
||||
return l.GetName()
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// loadStorageSize looks up the SizeGB for this storage in live storages.
|
||||
func (p *PVCSetter) loadStorageSize(peerID string) (string, error) {
|
||||
res := oclib.NewRequest(oclib.LibDataEnum(oclib.LIVE_STORAGE), "", peerID, []string{}, nil).LoadAll(false)
|
||||
if res.Err != "" {
|
||||
return "", fmt.Errorf("loadStorageSize: %s", res.Err)
|
||||
}
|
||||
for _, dbo := range res.Data {
|
||||
l := dbo.(*live.LiveStorage)
|
||||
if slices.Contains(l.ResourcesID, p.StorageID) && l.SizeGB > 0 {
|
||||
return fmt.Sprintf("%dGi", l.SizeGB), nil
|
||||
}
|
||||
}
|
||||
return "10Gi", nil
|
||||
}
|
||||
Reference in New Issue
Block a user