From 729bba68b77004e0f37376729179c9bf8218b5bd Mon Sep 17 00:00:00 2001 From: Blake Devcich Date: Wed, 24 Jul 2024 12:39:26 -0500 Subject: [PATCH 01/13] Use nnfv1alpha1.DataMovementInitiator from nnf-sos Signed-off-by: Blake Devcich --- .../compute/server/servers/server_default.go | 10 ++- go.mod | 2 +- go.sum | 4 +- .../controller/datamovement_controller.go | 2 - .../api/v1alpha1/nnf_datamovement_types.go | 15 ++++ .../api/v1alpha1/nnfstorageprofile_types.go | 32 +++++++++ .../api/v1alpha1/zz_generated.deepcopy.go | 38 +++++++--- .../nnf.cray.hpe.com_nnfstorageprofiles.yaml | 69 +++++++++++++++++++ vendor/modules.txt | 2 +- 9 files changed, 153 insertions(+), 21 deletions(-) diff --git a/daemons/compute/server/servers/server_default.go b/daemons/compute/server/servers/server_default.go index d47a1c6b..14be41d9 100644 --- a/daemons/compute/server/servers/server_default.go +++ b/daemons/compute/server/servers/server_default.go @@ -59,8 +59,6 @@ import ( lusv1beta1 "github.com/NearNodeFlash/lustre-fs-operator/api/v1beta1" nnfv1alpha1 "github.com/NearNodeFlash/nnf-sos/api/v1alpha1" - dmctrl "github.com/NearNodeFlash/nnf-dm/internal/controller" - pb "github.com/NearNodeFlash/nnf-dm/daemons/compute/client-go/api" "github.com/NearNodeFlash/nnf-dm/daemons/compute/server/auth" @@ -245,7 +243,7 @@ func (s *defaultServer) setupWithManager(mgr ctrl.Manager) error { p := predicate.Funcs{ CreateFunc: func(ce event.CreateEvent) bool { return false }, UpdateFunc: func(ue event.UpdateEvent) bool { - if initiator := ue.ObjectNew.GetLabels()[dmctrl.InitiatorLabel]; initiator == s.name { + if initiator := ue.ObjectNew.GetLabels()[nnfv1alpha1.DataMovementInitiatorLabel]; initiator == s.name { return true } return false @@ -444,8 +442,8 @@ func (s *defaultServer) createNnfDataMovement(ctx context.Context, req *pb.DataM // Use the data movement namespace. Namespace: nnfv1alpha1.DataMovementNamespace, Labels: map[string]string{ - dmctrl.InitiatorLabel: s.name, - nnfv1alpha1.DirectiveIndexLabel: dwIndex, + nnfv1alpha1.DataMovementInitiatorLabel: s.name, + nnfv1alpha1.DirectiveIndexLabel: dwIndex, }, }, Spec: nnfv1alpha1.NnfDataMovementSpec{ @@ -480,7 +478,7 @@ func (s *defaultServer) createNnfNodeDataMovement(ctx context.Context, req *pb.D GenerateName: nodeNameBase, Namespace: s.namespace, // Use the rabbit Labels: map[string]string{ - dmctrl.InitiatorLabel: s.name, + nnfv1alpha1.DataMovementInitiatorLabel: s.name, }, }, Spec: nnfv1alpha1.NnfDataMovementSpec{ diff --git a/go.mod b/go.mod index 1f45d2a2..16c30fa7 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf - github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240716150554-cdaa6e380157 + github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240724173133-de31c275611b github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.32.0 github.com/prometheus/client_golang v1.16.0 diff --git a/go.sum b/go.sum index c1d87058..d5e887d1 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf/go.mod h1:N5X1obpl0mBI0VoCJdQhv7cFXOC6g3VlXj712qWj0JE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 h1:7eT5mOVSNwtacIcGhzMAsi8EVbeS4zk9QwThG2f0GHE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5/go.mod h1:oxdwMqfttOF9dabJhqrWlirCnMk8/8eyLMwl+hducjk= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240716150554-cdaa6e380157 h1:gWD8QAOmLD64V9XMUZQCJHexeSZoHq0gCjfsVYYcbU8= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240716150554-cdaa6e380157/go.mod h1:+w5PxxJlQ82dwsxxYhFJOunwyssv1/MHMiJoReML3s0= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240724173133-de31c275611b h1:SgnslHt8gdzg/SiU3VzvlDvagKN46GSma9n6rclJQEQ= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240724173133-de31c275611b/go.mod h1:+w5PxxJlQ82dwsxxYhFJOunwyssv1/MHMiJoReML3s0= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/internal/controller/datamovement_controller.go b/internal/controller/datamovement_controller.go index 4807a919..acc60add 100644 --- a/internal/controller/datamovement_controller.go +++ b/internal/controller/datamovement_controller.go @@ -62,8 +62,6 @@ import ( const ( finalizer = "dm.cray.hpe.com" - InitiatorLabel = "dm.cray.hpe.com/initiator" - // DM ConfigMap Info configMapName = "nnf-dm-config" configMapNamespace = nnfv1alpha1.DataMovementNamespace diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go index bb6dcd11..4c700ac4 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go @@ -227,6 +227,11 @@ const ( // DataMovementTeardownStateLabel is the label applied to Data Movement and related resources that describes // the workflow state when the resource is no longer need and can be safely deleted. DataMovementTeardownStateLabel = "nnf.cray.hpe.com/teardown_state" + + // DataMovementInitiatorLabel is the label applied to Data Movement resources that describes the origin of + // data movement request. This would be from a copy_in/copy_out directive or from a compute node via the + // Copy Offload API (i.e. nnf-dm daemon). + DataMovementInitiatorLabel = "dm.cray.hpe.com/initiator" ) func AddDataMovementTeardownStateLabel(object metav1.Object, state dwsv1alpha2.WorkflowState) { @@ -239,6 +244,16 @@ func AddDataMovementTeardownStateLabel(object metav1.Object, state dwsv1alpha2.W object.SetLabels(labels) } +func AddDataMovementInitiatorLabel(object metav1.Object, initiator string) { + labels := object.GetLabels() + if labels == nil { + labels = make(map[string]string) + } + + labels[DataMovementInitiatorLabel] = initiator + object.SetLabels(labels) +} + func init() { SchemeBuilder.Register(&NnfDataMovement{}, &NnfDataMovementList{}) } diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfstorageprofile_types.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfstorageprofile_types.go index c45f5184..2c90bb2a 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfstorageprofile_types.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfstorageprofile_types.go @@ -58,6 +58,10 @@ type NnfStorageProfileLustreMiscOptions struct { // +kubebuilder:validation:Minimum:=1 // +kubebuilder:validation:Maximum:=10 Scale int `json:"scale,omitempty"` + + // Storagelabels defines a list of labels that are added to the DirectiveBreakdown + // labels constraint. This restricts allocations to Storage resources with these labels + StorageLabels []string `json:"storageLabels,omitempty"` } // NnfStorageProfileLustreData defines the Lustre-specific configuration @@ -88,6 +92,10 @@ type NnfStorageProfileLustreData struct { // +kubebuilder:default:=false ExclusiveMDT bool `json:"exclusiveMdt,omitempty"` + // CapacityScalingFactor is a scaling factor for the OST capacity requested in the DirectiveBreakdown + // +kubebuilder:default:="1.0" + CapacityScalingFactor string `json:"capacityScalingFactor,omitempty"` + // StandaloneMGTPoolName creates a Lustre MGT without a MDT or OST. This option can only be used when creating // a persistent Lustre instance. The MGS is placed into a named pool that can be used by the "ExternalMGS" option. // Multiple pools can be created. @@ -188,18 +196,42 @@ type NnfStorageProfileLVMLvChangeCmdLines struct { type NnfStorageProfileGFS2Data struct { // CmdLines contains commands to create volumes and filesystems. CmdLines NnfStorageProfileCmdLines `json:"commandlines,omitempty"` + + // Storagelabels defines a list of labels that are added to the DirectiveBreakdown + // labels constraint. This restricts allocations to Storage resources with these labels + StorageLabels []string `json:"storageLabels,omitempty"` + + // CapacityScalingFactor is a scaling factor for the capacity requested in the DirectiveBreakdown + // +kubebuilder:default:="1.0" + CapacityScalingFactor string `json:"capacityScalingFactor,omitempty"` } // NnfStorageProfileXFSData defines the XFS-specific configuration type NnfStorageProfileXFSData struct { // CmdLines contains commands to create volumes and filesystems. CmdLines NnfStorageProfileCmdLines `json:"commandlines,omitempty"` + + // Storagelabels defines a list of labels that are added to the DirectiveBreakdown + // labels constraint. This restricts allocations to Storage resources with these labels + StorageLabels []string `json:"storageLabels,omitempty"` + + // CapacityScalingFactor is a scaling factor for the capacity requested in the DirectiveBreakdown + // +kubebuilder:default:="1.0" + CapacityScalingFactor string `json:"capacityScalingFactor,omitempty"` } // NnfStorageProfileRawData defines the Raw-specific configuration type NnfStorageProfileRawData struct { // CmdLines contains commands to create volumes and filesystems. CmdLines NnfStorageProfileCmdLines `json:"commandlines,omitempty"` + + // Storagelabels defines a list of labels that are added to the DirectiveBreakdown + // labels constraint. This restricts allocations to Storage resources with these labels + StorageLabels []string `json:"storageLabels,omitempty"` + + // CapacityScalingFactor is a scaling factor for the capacity requested in the DirectiveBreakdown + // +kubebuilder:default:="1.0" + CapacityScalingFactor string `json:"capacityScalingFactor,omitempty"` } // NnfStorageProfileData defines the desired state of NnfStorageProfile diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go index 4f0fce8c..33709572 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go @@ -1382,7 +1382,7 @@ func (in *NnfStorageProfile) DeepCopyInto(out *NnfStorageProfile) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Data = in.Data + in.Data.DeepCopyInto(&out.Data) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfStorageProfile. @@ -1423,10 +1423,10 @@ func (in *NnfStorageProfileCmdLines) DeepCopy() *NnfStorageProfileCmdLines { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NnfStorageProfileData) DeepCopyInto(out *NnfStorageProfileData) { *out = *in - out.LustreStorage = in.LustreStorage - out.GFS2Storage = in.GFS2Storage - out.XFSStorage = in.XFSStorage - out.RawStorage = in.RawStorage + in.LustreStorage.DeepCopyInto(&out.LustreStorage) + in.GFS2Storage.DeepCopyInto(&out.GFS2Storage) + in.XFSStorage.DeepCopyInto(&out.XFSStorage) + in.RawStorage.DeepCopyInto(&out.RawStorage) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfStorageProfileData. @@ -1443,6 +1443,11 @@ func (in *NnfStorageProfileData) DeepCopy() *NnfStorageProfileData { func (in *NnfStorageProfileGFS2Data) DeepCopyInto(out *NnfStorageProfileGFS2Data) { *out = *in out.CmdLines = in.CmdLines + if in.StorageLabels != nil { + in, out := &in.StorageLabels, &out.StorageLabels + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfStorageProfileGFS2Data. @@ -1539,10 +1544,10 @@ func (in *NnfStorageProfileLustreData) DeepCopyInto(out *NnfStorageProfileLustre out.MdtCmdLines = in.MdtCmdLines out.MgtMdtCmdLines = in.MgtMdtCmdLines out.OstCmdLines = in.OstCmdLines - out.MgtOptions = in.MgtOptions - out.MdtOptions = in.MdtOptions - out.MgtMdtOptions = in.MgtMdtOptions - out.OstOptions = in.OstOptions + in.MgtOptions.DeepCopyInto(&out.MgtOptions) + in.MdtOptions.DeepCopyInto(&out.MdtOptions) + in.MgtMdtOptions.DeepCopyInto(&out.MgtMdtOptions) + in.OstOptions.DeepCopyInto(&out.OstOptions) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfStorageProfileLustreData. @@ -1558,6 +1563,11 @@ func (in *NnfStorageProfileLustreData) DeepCopy() *NnfStorageProfileLustreData { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NnfStorageProfileLustreMiscOptions) DeepCopyInto(out *NnfStorageProfileLustreMiscOptions) { *out = *in + if in.StorageLabels != nil { + in, out := &in.StorageLabels, &out.StorageLabels + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfStorageProfileLustreMiscOptions. @@ -1574,6 +1584,11 @@ func (in *NnfStorageProfileLustreMiscOptions) DeepCopy() *NnfStorageProfileLustr func (in *NnfStorageProfileRawData) DeepCopyInto(out *NnfStorageProfileRawData) { *out = *in out.CmdLines = in.CmdLines + if in.StorageLabels != nil { + in, out := &in.StorageLabels, &out.StorageLabels + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfStorageProfileRawData. @@ -1590,6 +1605,11 @@ func (in *NnfStorageProfileRawData) DeepCopy() *NnfStorageProfileRawData { func (in *NnfStorageProfileXFSData) DeepCopyInto(out *NnfStorageProfileXFSData) { *out = *in out.CmdLines = in.CmdLines + if in.StorageLabels != nil { + in, out := &in.StorageLabels, &out.StorageLabels + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfStorageProfileXFSData. diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfstorageprofiles.yaml b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfstorageprofiles.yaml index e698a8e2..3eb56816 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfstorageprofiles.yaml +++ b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfstorageprofiles.yaml @@ -45,6 +45,11 @@ spec: gfs2Storage: description: GFS2Storage defines the GFS2-specific configuration properties: + capacityScalingFactor: + default: "1.0" + description: CapacityScalingFactor is a scaling factor for the + capacity requested in the DirectiveBreakdown + type: string commandlines: description: CmdLines contains commands to create volumes and filesystems. @@ -118,6 +123,13 @@ spec: minus the "vgremove". type: string type: object + storageLabels: + description: |- + Storagelabels defines a list of labels that are added to the DirectiveBreakdown + labels constraint. This restricts allocations to Storage resources with these labels + items: + type: string + type: array type: object lustreStorage: description: LustreStorage defines the Lustre-specific configuration @@ -134,6 +146,11 @@ spec: description: CapacityMGT specifies the size of the MGT device. pattern: ^\d+(KiB|KB|MiB|MB|GiB|GB|TiB|TB)$ type: string + capacityScalingFactor: + default: "1.0" + description: CapacityScalingFactor is a scaling factor for the + OST capacity requested in the DirectiveBreakdown + type: string combinedMgtMdt: default: false description: CombinedMGTMDT indicates whether the MGT and MDT @@ -194,6 +211,13 @@ spec: maximum: 10 minimum: 1 type: integer + storageLabels: + description: |- + Storagelabels defines a list of labels that are added to the DirectiveBreakdown + labels constraint. This restricts allocations to Storage resources with these labels + items: + type: string + type: array required: - colocateComputes type: object @@ -262,6 +286,13 @@ spec: maximum: 10 minimum: 1 type: integer + storageLabels: + description: |- + Storagelabels defines a list of labels that are added to the DirectiveBreakdown + labels constraint. This restricts allocations to Storage resources with these labels + items: + type: string + type: array required: - colocateComputes type: object @@ -285,6 +316,13 @@ spec: maximum: 10 minimum: 1 type: integer + storageLabels: + description: |- + Storagelabels defines a list of labels that are added to the DirectiveBreakdown + labels constraint. This restricts allocations to Storage resources with these labels + items: + type: string + type: array required: - colocateComputes type: object @@ -338,6 +376,13 @@ spec: maximum: 10 minimum: 1 type: integer + storageLabels: + description: |- + Storagelabels defines a list of labels that are added to the DirectiveBreakdown + labels constraint. This restricts allocations to Storage resources with these labels + items: + type: string + type: array required: - colocateComputes type: object @@ -355,6 +400,11 @@ spec: rawStorage: description: RawStorage defines the Raw-specific configuration properties: + capacityScalingFactor: + default: "1.0" + description: CapacityScalingFactor is a scaling factor for the + capacity requested in the DirectiveBreakdown + type: string commandlines: description: CmdLines contains commands to create volumes and filesystems. @@ -428,10 +478,22 @@ spec: minus the "vgremove". type: string type: object + storageLabels: + description: |- + Storagelabels defines a list of labels that are added to the DirectiveBreakdown + labels constraint. This restricts allocations to Storage resources with these labels + items: + type: string + type: array type: object xfsStorage: description: XFSStorage defines the XFS-specific configuration properties: + capacityScalingFactor: + default: "1.0" + description: CapacityScalingFactor is a scaling factor for the + capacity requested in the DirectiveBreakdown + type: string commandlines: description: CmdLines contains commands to create volumes and filesystems. @@ -505,6 +567,13 @@ spec: minus the "vgremove". type: string type: object + storageLabels: + description: |- + Storagelabels defines a list of labels that are added to the DirectiveBreakdown + labels constraint. This restricts allocations to Storage resources with these labels + items: + type: string + type: array type: object required: - gfs2Storage diff --git a/vendor/modules.txt b/vendor/modules.txt index 1d49a84e..a6be8aa3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,7 +10,7 @@ github.com/NearNodeFlash/lustre-fs-operator/config/crd/bases # github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 ## explicit; go 1.19 github.com/NearNodeFlash/nnf-ec/pkg/rfsf/pkg/models -# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240716150554-cdaa6e380157 +# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240724173133-de31c275611b ## explicit; go 1.21 github.com/NearNodeFlash/nnf-sos/api/v1alpha1 github.com/NearNodeFlash/nnf-sos/config/crd/bases From 419cf169e4dec021ad52db887ba97c22a6b7f6c0 Mon Sep 17 00:00:00 2001 From: Blake Devcich <89158881+bdevcich@users.noreply.github.com> Date: Mon, 29 Jul 2024 08:58:53 -0500 Subject: [PATCH 02/13] Parse stats from dcp output (#189) Grab the end stats from dcp output and store it in the command status. Signed-off-by: Blake Devcich --- go.mod | 4 +- go.sum | 8 +- .../controller/datamovement_controller.go | 124 +++++++++++++++++- .../dws/utils/dwdparse/dwdparse.go | 15 ++- .../api/v1alpha1/nnf_datamovement_types.go | 40 +++++- .../api/v1alpha1/zz_generated.deepcopy.go | 20 +++ .../nnf.cray.hpe.com_nnfdatamovements.yaml | 51 ++++++- vendor/modules.txt | 4 +- 8 files changed, 236 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index 16c30fa7..7b0ec4b3 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf - github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240724173133-de31c275611b + github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240729130730-8f01fd2116ea github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.32.0 github.com/prometheus/client_golang v1.16.0 @@ -73,7 +73,7 @@ require ( ) require ( - github.com/DataWorkflowServices/dws v0.0.1-0.20240710175416-1e4b39039a88 + github.com/DataWorkflowServices/dws v0.0.1-0.20240726140248-bd9f85356c73 go.openly.dev/pointy v1.3.0 ) diff --git a/go.sum b/go.sum index d5e887d1..23a60758 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ -github.com/DataWorkflowServices/dws v0.0.1-0.20240710175416-1e4b39039a88 h1:jCb+vMAx2nV2fpL/uH8KbxDlQNt+mZcNvUxKM/O8/GM= -github.com/DataWorkflowServices/dws v0.0.1-0.20240710175416-1e4b39039a88/go.mod h1:6MrEEHISskyooSKcKU6R3mFqH6Yh6KzWgajhcw2s+nM= +github.com/DataWorkflowServices/dws v0.0.1-0.20240726140248-bd9f85356c73 h1:bq1AaHhdaeuaq+ibNk/UIMExXuLicfQCir25xKHnEck= +github.com/DataWorkflowServices/dws v0.0.1-0.20240726140248-bd9f85356c73/go.mod h1:6MrEEHISskyooSKcKU6R3mFqH6Yh6KzWgajhcw2s+nM= github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf h1:ArBI1LR+BBZ9lF+Aohv49RhTpmRqIXLz4L/h45qQT4k= github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf/go.mod h1:N5X1obpl0mBI0VoCJdQhv7cFXOC6g3VlXj712qWj0JE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 h1:7eT5mOVSNwtacIcGhzMAsi8EVbeS4zk9QwThG2f0GHE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5/go.mod h1:oxdwMqfttOF9dabJhqrWlirCnMk8/8eyLMwl+hducjk= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240724173133-de31c275611b h1:SgnslHt8gdzg/SiU3VzvlDvagKN46GSma9n6rclJQEQ= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240724173133-de31c275611b/go.mod h1:+w5PxxJlQ82dwsxxYhFJOunwyssv1/MHMiJoReML3s0= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240729130730-8f01fd2116ea h1:WZCoDgPMs8+3jle4iJnx4EaPlBLd6pr2ks+o8U4yy10= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240729130730-8f01fd2116ea/go.mod h1:WBbrMgTEGvnFbbuQglDBoLl/KvcsC3F/CKY9jq5hWgU= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/internal/controller/datamovement_controller.go b/internal/controller/datamovement_controller.go index acc60add..bf5a7e23 100644 --- a/internal/controller/datamovement_controller.go +++ b/internal/controller/datamovement_controller.go @@ -74,6 +74,42 @@ const ( // Copied 1.000 GiB (10%) in 1.001 secs (4.174 GiB/s) 9 secs left ..." var progressRe = regexp.MustCompile(`Copied.+\(([[:digit:]]{1,3})%\)`) +// Regexes to scrape the stats output of the `dcp` command once it's done. Example output: +/* +Copied 18.626 GiB (100%) in 171.434 secs (111.259 MiB/s) done +Copy data: 18.626 GiB (20000000000 bytes) +Copy rate: 111.258 MiB/s (20000000000 bytes in 171.434 seconds) +Syncing data to disk. +Sync completed in 0.017 seconds. +Fixing permissions. +Updated 2 items in 0.003 seconds (742.669 items/sec) +Syncing directory updates to disk. +Sync completed in 0.001 seconds. +Started: Jul-25-2024,16:44:33 +Completed: Jul-25-2024,16:47:25 +Seconds: 171.458 +Items: 2 + Directories: 1 + Files: 1 + Links: 0 +Data: 18.626 GiB (20000000000 bytes) +Rate: 111.243 MiB/s (20000000000 bytes in 171.458 seconds) +*/ +type statsRegex struct { + name string + regex *regexp.Regexp +} + +var dcpStatsRegexes = []statsRegex{ + {"seconds", regexp.MustCompile(`Seconds: ([[:digit:].]+)`)}, + {"items", regexp.MustCompile(`Items: ([[:digit:]]+)`)}, + {"dirs", regexp.MustCompile(`Directories: ([[:digit:]]+)`)}, + {"files", regexp.MustCompile(`Files: ([[:digit:]]+)`)}, + {"links", regexp.MustCompile(`Files: ([[:digit:]]+)`)}, + {"data", regexp.MustCompile(`Data: (.*)`)}, + {"rate", regexp.MustCompile(`Rate: (.*)`)}, +} + // DataMovementReconciler reconciles a DataMovement object type DataMovementReconciler struct { client.Client @@ -335,15 +371,17 @@ func (r *DataMovementReconciler) Reconcile(ctx context.Context, req ctrl.Request } // If it's a progress line, grab the percentage - match := progressRe.FindStringSubmatch(line) - if len(match) > 0 { - progress, err := strconv.Atoi(match[1]) - if err != nil { - log.Error(err, "failed to parse progress output", "match", match) + if err := parseDcpProgress(line, &cmdStatus); err != nil { + log.Error(err, "failed to parse progress", "line", line) + return + } + + // Collect stats only when finished + if cmdStatus.ProgressPercentage != nil && *cmdStatus.ProgressPercentage >= 100 { + if err := parseDcpStats(line, &cmdStatus); err != nil { + log.Error(err, "failed to parse stats", "line", line) return } - progressInt32 := int32(progress) - cmdStatus.ProgressPercentage = &progressInt32 } // Always update LastMessage and timing @@ -460,6 +498,78 @@ func (r *DataMovementReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, nil } +func parseDcpProgress(line string, cmdStatus *nnfv1alpha1.NnfDataMovementCommandStatus) error { + match := progressRe.FindStringSubmatch(line) + if len(match) > 0 { + progress, err := strconv.Atoi(match[1]) + if err != nil { + return fmt.Errorf("failed to parse progress output: %w", err) + } + progressInt32 := int32(progress) + cmdStatus.ProgressPercentage = &progressInt32 + } + + return nil +} + +// Go through the list of dcp stat regexes, parse them, and put them in their appropriate place in cmdStatus +func parseDcpStats(line string, cmdStatus *nnfv1alpha1.NnfDataMovementCommandStatus) error { + for _, s := range dcpStatsRegexes { + match := s.regex.FindStringSubmatch(line) + if len(match) > 0 { + matched := true // default case will set this to false + + // Each regex is parsed depending on its type (e.g. float, int, string) and then stored + // in a different place in cmdStatus + switch s.name { + case "seconds": + cmdStatus.Seconds = match[1] + case "items": + items, err := strconv.Atoi(match[1]) + if err != nil { + return fmt.Errorf("failed to parse Items output: %w", err) + } + i32 := int32(items) + cmdStatus.Items = &i32 + case "dirs": + dirs, err := strconv.Atoi(match[1]) + if err != nil { + return fmt.Errorf("failed to parse Directories output: %w", err) + } + i32 := int32(dirs) + cmdStatus.Directories = &i32 + case "files": + files, err := strconv.Atoi(match[1]) + if err != nil { + return fmt.Errorf("failed to parse Directories output: %w", err) + } + i32 := int32(files) + cmdStatus.Files = &i32 + case "links": + links, err := strconv.Atoi(match[1]) + if err != nil { + return fmt.Errorf("failed to parse Links output: %w", err) + } + i32 := int32(links) + cmdStatus.Links = &i32 + case "data": + cmdStatus.Data = match[1] + case "rate": + cmdStatus.Rate = match[1] + default: + matched = false // if we got here then nothing happened, so try the next regex + } + + // if one of the regexes matched, then we're done + if matched { + return nil + } + } + } + + return nil +} + func buildDMCommand(ctx context.Context, profile dmConfigProfile, hostfile string, dm *nnfv1alpha1.NnfDataMovement) ([]string, error) { log := log.FromContext(ctx) userConfig := dm.Spec.UserConfig != nil diff --git a/vendor/github.com/DataWorkflowServices/dws/utils/dwdparse/dwdparse.go b/vendor/github.com/DataWorkflowServices/dws/utils/dwdparse/dwdparse.go index b3df9840..212ab7f0 100644 --- a/vendor/github.com/DataWorkflowServices/dws/utils/dwdparse/dwdparse.go +++ b/vendor/github.com/DataWorkflowServices/dws/utils/dwdparse/dwdparse.go @@ -40,6 +40,8 @@ type DWDirectiveRuleDef struct { UniqueWithin string `json:"uniqueWithin,omitempty"` } +const emptyValue = "$$empty_value_123456$$" + // DWDirectiveRuleSpec defines the desired state of DWDirective // +kubebuilder:object:generate=true type DWDirectiveRuleSpec struct { @@ -80,7 +82,9 @@ func BuildArgsMap(dwd string) (map[string]string, error) { } if len(keyValue) == 1 { - argsMap[keyValue[0]] = "true" + // We won't know how to interpret an empty value--whether it's allowed, + // or what its type should be--until ValidateArgs(). + argsMap[keyValue[0]] = emptyValue } else if len(keyValue) == 2 { argsMap[keyValue[0]] = keyValue[1] } else { @@ -138,8 +142,13 @@ func ValidateArgs(spec DWDirectiveRuleSpec, args map[string]string, uniqueMap ma return err } - if rule.IsValueRequired && len(v) == 0 { - return fmt.Errorf("argument '%s' requires value", k) + if v == emptyValue { + if rule.Type == "bool" && !rule.IsValueRequired { + // Booleans default to true. + v = "true" + } else if rule.IsValueRequired { + return fmt.Errorf("argument '%s' requires value", k) + } } switch rule.Type { diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go index 4c700ac4..2a37a77d 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go @@ -126,19 +126,47 @@ type NnfDataMovementCommandStatus struct { // ElapsedTime reflects the elapsed time since the underlying data movement command started. ElapsedTime metav1.Duration `json:"elapsedTime,omitempty"` - // Progress refects the progress of the underlying data movement command as captured from standard output. - // A best effort is made to parse the command output as a percentage. If no progress has - // yet to be measured than this field is omitted. If the latest command output does not - // contain a valid percentage, then the value is unchanged from the previously parsed value. + // ProgressPercentage refects the progress of the underlying data movement command as captured from + // standard output. A best effort is made to parse the command output as a percentage. If no + // progress has yet to be measured than this field is omitted. If the latest command output does + // not contain a valid percentage, then the value is unchanged from the previously parsed value. ProgressPercentage *int32 `json:"progress,omitempty"` // LastMessage reflects the last message received over standard output or standard error as // captured by the underlying data movement command. LastMessage string `json:"lastMessage,omitempty"` - // LastMessageTime reflects the time at which the last message was received over standard output or - // standard error by the underlying data movement command. + // LastMessageTime reflects the time at which the last message was received over standard output + // or standard error by the underlying data movement command. LastMessageTime metav1.MicroTime `json:"lastMessageTime,omitempty"` + + // Seconds is parsed from the dcp output when the command is finished. + Seconds string `json:"seconds,omitempty"` + + // Items is parsed from the dcp output when the command is finished. This is a total of + // the number of directories, files, and links that dcp copied. + Items *int32 `json:"items,omitempty"` + + // Directories is parsed from the dcp output when the command is finished. This is the number of + // directories that dcp copied. Note: This value may be inflated due to NNF index mount + // directories when copying from XFS or GFS2 filesystems. + Directories *int32 `json:"directories,omitempty"` + + // Files is parsed from the dcp output when the command is finished. This is the number of files + // that dcp copied. + Files *int32 `json:"files,omitempty"` + + // Links is parsed from the dcp output when the command is finished. This is the number of links + // that dcp copied. + Links *int32 `json:"links,omitempty"` + + // Data is parsed from the dcp output when the command is finished. This is the total amount of + // data copied by dcp. + Data string `json:"data,omitempty"` + + // Rate is parsed from the dcp output when the command is finished. This is transfer rate of the + // data copied by dcp. + Rate string `json:"rate,omitempty"` } // NnfDataMovementStatus defines the observed state of NnfDataMovement diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go index 33709572..e0f2a631 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go @@ -296,6 +296,26 @@ func (in *NnfDataMovementCommandStatus) DeepCopyInto(out *NnfDataMovementCommand **out = **in } in.LastMessageTime.DeepCopyInto(&out.LastMessageTime) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = new(int32) + **out = **in + } + if in.Directories != nil { + in, out := &in.Directories, &out.Directories + *out = new(int32) + **out = **in + } + if in.Files != nil { + in, out := &in.Files, &out.Files + *out = new(int32) + **out = **in + } + if in.Links != nil { + in, out := &in.Links, &out.Links + *out = new(int32) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfDataMovementCommandStatus. diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovements.yaml b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovements.yaml index 026ef147..d4e1660b 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovements.yaml +++ b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovements.yaml @@ -242,10 +242,34 @@ spec: command: description: The command that was executed during data movement. type: string + data: + description: |- + Data is parsed from the dcp output when the command is finished. This is the total amount of + data copied by dcp. + type: string + directories: + description: |- + Directories is parsed from the dcp output when the command is finished. This is the number of + directories that dcp copied. Note: This value may be inflated due to NNF index mount + directories when copying from XFS or GFS2 filesystems. + format: int32 + type: integer elapsedTime: description: ElapsedTime reflects the elapsed time since the underlying data movement command started. type: string + files: + description: |- + Files is parsed from the dcp output when the command is finished. This is the number of files + that dcp copied. + format: int32 + type: integer + items: + description: |- + Items is parsed from the dcp output when the command is finished. This is a total of + the number of directories, files, and links that dcp copied. + format: int32 + type: integer lastMessage: description: |- LastMessage reflects the last message received over standard output or standard error as @@ -253,18 +277,33 @@ spec: type: string lastMessageTime: description: |- - LastMessageTime reflects the time at which the last message was received over standard output or - standard error by the underlying data movement command. + LastMessageTime reflects the time at which the last message was received over standard output + or standard error by the underlying data movement command. format: date-time type: string + links: + description: |- + Links is parsed from the dcp output when the command is finished. This is the number of links + that dcp copied. + format: int32 + type: integer progress: description: |- - Progress refects the progress of the underlying data movement command as captured from standard output. - A best effort is made to parse the command output as a percentage. If no progress has - yet to be measured than this field is omitted. If the latest command output does not - contain a valid percentage, then the value is unchanged from the previously parsed value. + Progress refects the progress of the underlying data movement command as captured from + standard output. A best effort is made to parse the command output as a percentage. If no + progress has yet to be measured than this field is omitted. If the latest command output does + not contain a valid percentage, then the value is unchanged from the previously parsed value. format: int32 type: integer + rate: + description: |- + Rate is parsed from the dcp output when the command is finished. This is transfer rate of the + data copied by dcp. + type: string + seconds: + description: Seconds is parsed from the dcp output when the command + is finished. + type: string type: object endTime: description: EndTime reflects the time at which the Data Movement diff --git a/vendor/modules.txt b/vendor/modules.txt index a6be8aa3..94b350c2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/DataWorkflowServices/dws v0.0.1-0.20240710175416-1e4b39039a88 +# github.com/DataWorkflowServices/dws v0.0.1-0.20240726140248-bd9f85356c73 ## explicit; go 1.21 github.com/DataWorkflowServices/dws/api/v1alpha2 github.com/DataWorkflowServices/dws/utils/dwdparse @@ -10,7 +10,7 @@ github.com/NearNodeFlash/lustre-fs-operator/config/crd/bases # github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 ## explicit; go 1.19 github.com/NearNodeFlash/nnf-ec/pkg/rfsf/pkg/models -# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240724173133-de31c275611b +# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240729130730-8f01fd2116ea ## explicit; go 1.21 github.com/NearNodeFlash/nnf-sos/api/v1alpha1 github.com/NearNodeFlash/nnf-sos/config/crd/bases From 45a8a3da1caf6b84e7de3a98a58853109b2fe7dc Mon Sep 17 00:00:00 2001 From: Dean Roehrich Date: Thu, 1 Aug 2024 12:35:24 -0500 Subject: [PATCH 03/13] Verify auto-gen files in workflow (#190) Signed-off-by: Dean Roehrich --- .github/workflows/main.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c456dca4..a8b9552f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,6 +40,13 @@ jobs: cat ${GITHUB_ENV} shell: bash + - name: "Verify auto-generated files" + run: | + make manifests generate + if [[ $(git status -s | wc -l) -gt 0 ]]; then \ + git status; exit 1; \ + fi + - name: "Docker metadata" id: meta uses: docker/metadata-action@v4 From 9309f88bb86a638ba05bfe455460a4cc986965d4 Mon Sep 17 00:00:00 2001 From: Dean Roehrich Date: Fri, 2 Aug 2024 15:53:54 -0500 Subject: [PATCH 04/13] Bump envtest to 1.29 (#192) Signed-off-by: Dean Roehrich --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ae8ea2ca..70ade671 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ CONTAINER_BUILDARGS=--build-arg NNFMFU_TAG_BASE=$(NNFMFU_TAG_BASE) --build-arg N BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.28.0 +ENVTEST_K8S_VERSION = 1.29.0 # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) From 9e2c8d12461f3507bfbac5cb98da997a463ce925 Mon Sep 17 00:00:00 2001 From: Dean Roehrich Date: Mon, 5 Aug 2024 14:19:43 -0500 Subject: [PATCH 05/13] Squash the warnings about patchesStrategicMerge (#193) Signed-off-by: Dean Roehrich --- config/default/kustomization.yaml | 10 +++++----- config/manager/kustomization.yaml | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index a662aad0..e3cfe8ba 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -24,24 +24,24 @@ resources: # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. #- ../prometheus -patchesStrategicMerge: +patches: # Protect the /metrics endpoint by putting it behind auth. # If you want your controller-manager to expose the /metrics # endpoint w/o any authn/z, please comment the following line. -- manager_auth_proxy_patch.yaml +- path: manager_auth_proxy_patch.yaml # Mount the controller config file for loading manager configurations # through a ComponentConfig type -#- manager_config_patch.yaml +#- path: manager_config_patch.yaml # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml -# - manager_webhook_patch.yaml +# - path: manager_webhook_patch.yaml # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. # 'CERTMANAGER' needs to be enabled to use ca injection -# - webhookcainjection_patch.yaml +# - path: webhookcainjection_patch.yaml # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. # Uncomment the following replacements to add the cert-manager CA injection annotations diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 873b0a4b..a4482e3a 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -4,8 +4,8 @@ resources: generatorOptions: disableNameSuffixHash: true -#patchesStrategicMerge: -#- manager_imagepullsecret_patch.yaml +#patches: +#- path: manager_imagepullsecret_patch.yaml configMapGenerator: - files: From 27cfe151f3cc45b0bacffdcc6acd30ef82b073f3 Mon Sep 17 00:00:00 2001 From: Blake Devcich Date: Thu, 1 Aug 2024 14:23:48 -0500 Subject: [PATCH 06/13] Use NnfDataMovementProfiles nnf-dm uses a configmap to store its configuration in. This is not consistent with the other means of configuration (i.e. Storage and Container Profiles). This change removes the nnf-dm-config map and swaps it with using NnfDataMovementProfiles. Pinned profiles are used for copy_in/copy_out directives. Non-pinned profiles are used for the Copy Offload API since the user can select any profile they wish and can change profiles with each request. This means that the nnf-dm reconciler now needs access to the `nnf-system` namespace to get the non-pinned profiles. Signed-off-by: Blake Devcich --- .vscode/launch.json | 2 +- cmd/main.go | 2 + config/default/kustomization.yaml | 1 - config/dm_config/kustomization.yaml | 10 - config/dm_config/nnf-dm-config.yaml | 44 ---- config/rbac/daemon_role.yaml | 8 + config/rbac/role.yaml | 8 + .../compute/server/servers/server_default.go | 60 +++++- go.mod | 6 +- go.sum | 8 +- .../controller/datamovement_controller.go | 92 ++++---- .../datamovement_controller_test.go | 197 ++++++++++-------- .../dws/api/v1alpha2/resource.go | 7 +- .../api/v1alpha1/nnf_datamovement_types.go | 20 +- .../v1alpha1/nnfdatamovementprofile_types.go | 100 +++++++++ .../api/v1alpha1/zz_generated.deepcopy.go | 74 +++++++ ....cray.hpe.com_nnfdatamovementprofiles.yaml | 114 ++++++++++ .../nnf.cray.hpe.com_nnfdatamovements.yaml | 60 +++++- vendor/modules.txt | 4 +- 19 files changed, 582 insertions(+), 235 deletions(-) delete mode 100644 config/dm_config/kustomization.yaml delete mode 100644 config/dm_config/nnf-dm-config.yaml create mode 100644 vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go create mode 100644 vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml diff --git a/.vscode/launch.json b/.vscode/launch.json index 2552aa34..89a08cdd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -56,7 +56,7 @@ "-ginkgo.failFast", ], "env": { - "KUBEBUILDER_ASSETS": "${workspaceRoot}/bin/k8s/1.25.0-darwin-amd64", + "KUBEBUILDER_ASSETS": "${workspaceRoot}/bin/k8s/1.28.0-darwin-arm64", "GOMEGA_DEFAULT_EVENTUALLY_TIMEOUT": "10m", "GOMEGA_DEFAULT_EVENTUALLY_POLLING_INTERVAL": "500ms", }, diff --git a/cmd/main.go b/cmd/main.go index 83139428..e9325e52 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -179,6 +179,7 @@ func (*defaultController) SetOptions(opts *ctrl.Options) { namespaceCache := make(map[string]cache.Config) namespaceCache[corev1.NamespaceDefault] = cache.Config{} namespaceCache[nnfv1alpha1.DataMovementNamespace] = cache.Config{} + namespaceCache[nnfv1alpha1.DataMovementProfileNamespace] = cache.Config{} opts.Cache = cache.Options{DefaultNamespaces: namespaceCache} } @@ -205,6 +206,7 @@ func (*nodeController) SetOptions(opts *ctrl.Options) { namespaceCache := make(map[string]cache.Config) namespaceCache[corev1.NamespaceDefault] = cache.Config{} namespaceCache[nnfv1alpha1.DataMovementNamespace] = cache.Config{} + namespaceCache[nnfv1alpha1.DataMovementProfileNamespace] = cache.Config{} namespaceCache[os.Getenv("NNF_NODE_NAME")] = cache.Config{} opts.Cache = cache.Options{DefaultNamespaces: namespaceCache} } diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index e3cfe8ba..4cae9264 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -15,7 +15,6 @@ namePrefix: nnf-dm- resources: - ../rbac - ../manager - - ../dm_config # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml # - ../webhook diff --git a/config/dm_config/kustomization.yaml b/config/dm_config/kustomization.yaml deleted file mode 100644 index ef7be497..00000000 --- a/config/dm_config/kustomization.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -generatorOptions: - disableNameSuffixHash: true - -configMapGenerator: -- files: - - nnf-dm-config.yaml - name: config \ No newline at end of file diff --git a/config/dm_config/nnf-dm-config.yaml b/config/dm_config/nnf-dm-config.yaml deleted file mode 100644 index ab84e2b0..00000000 --- a/config/dm_config/nnf-dm-config.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Each profile is capable of providing different configurations for data movement. -profiles: - # Default profile that is used for all data movement activity. - default: - # The number of slots specified in the MPI hostfile. A value less than 1 disables the use - # of slots in the hostfile. - slots: 8 - - # The number of max_slots specified in the MPI hostfile. A value less than 1 disables the use - # of max_slots in the hostfile. - maxSlots: 0 - - # The full command to execute data movement. $VARS are replaced by the nnf software. Available - # $VARS: - # HOSTFILE: hostfile that is created and used for mpirun. Contains a list of hosts and the - # slots/max_slots for each host. This hostfile is created at `/tmp//hostfile` - # UID: User ID that is inherited from the Workflow - # GID: Group ID that is inherited from the Workflow - # SRC: source for the data movement - # DEST destination for the data movement - # default: command: ulimit -n 2048 && mpirun --allow-run-as-root --hostfile $HOSTFILE dcp --progress 1 --uid $UID --gid $GID $SRC $DEST - command: ulimit -n 2048 && mpirun --allow-run-as-root --hostfile $HOSTFILE dcp --progress 1 --uid $UID --gid $GID $SRC $DEST - - # If true, enable the command's stdout to be saved in the log when the command completes - # successfully. On failure, the output is always logged. - logStdout: false - - # Similar to logStdout, store the command's stdout in Status.Message when the command - # completes successfully. On failure, the output is always stored. - storeStdout: false - - # Same as default profile but tell dcp not to copy xattrs - no-xattr: - slots: 8 - maxSlots: 0 - command: ulimit -n 2048 && mpirun --allow-run-as-root --hostfile $HOSTFILE dcp --progress 1 --xattrs none --uid $UID --gid $GID $SRC $DEST - logStdout: false - storeStdout: false - -# NnfDataMovement resources have the ability to collect and store the progress percentage and the -# last few lines of output in the CommandStatus field. This number is used for the interval to collect -# the progress data. `dcp --progress N` must be included in the data movement command in order for -# progress to be collected. A value less than 1 disables this functionality. -progressIntervalSeconds: 5 diff --git a/config/rbac/daemon_role.yaml b/config/rbac/daemon_role.yaml index 9d24b176..c3cabb0f 100644 --- a/config/rbac/daemon_role.yaml +++ b/config/rbac/daemon_role.yaml @@ -53,6 +53,14 @@ rules: - patch - update - watch +- apiGroups: + - nnf.cray.hpe.com + resources: + - nnfdatamovementprofiles + verbs: + - get + - list + - watch - apiGroups: - nnf.cray.hpe.com resources: diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index e1c525ce..118aa94a 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -136,6 +136,14 @@ rules: - get - patch - update +- apiGroups: + - nnf.cray.hpe.com + resources: + - nnfdatamovementprofiles + verbs: + - get + - list + - watch - apiGroups: - nnf.cray.hpe.com resources: diff --git a/daemons/compute/server/servers/server_default.go b/daemons/compute/server/servers/server_default.go index 14be41d9..0f2134df 100644 --- a/daemons/compute/server/servers/server_default.go +++ b/daemons/compute/server/servers/server_default.go @@ -96,6 +96,7 @@ type defaultServer struct { // Ensure permissions are granted to access the system configuration; this is done so the NNF // Node Name can be found given a Node Name. //+kubebuilder:rbac:groups=dataworkflowservices.github.io,resources=systemconfigurations,verbs=get;list;watch +//+kubebuilder:rbac:groups=nnf.cray.hpe.com,resources=nnfdatamovementprofiles,verbs=get;list;watch func CreateDefaultServer(opts *ServerOptions) (*defaultServer, error) { @@ -237,7 +238,7 @@ func (s *defaultServer) StartManager() error { } // Setup two managers for watching the individual data movement type resources. They behave -// similarily, performing a reconcile only for updates to this node +// similarly, performing a reconcile only for updates to this node func (s *defaultServer) setupWithManager(mgr ctrl.Manager) error { p := predicate.Funcs{ @@ -355,6 +356,20 @@ func (s *defaultServer) Create(ctx context.Context, req *pb.DataMovementCreateRe }, nil } + // Dm Profile - no pinned profiles here since copy_offload could use any profile + profile, err := s.getProfile(ctx, req.Profile) + if err != nil { + return &pb.DataMovementCreateResponse{ + Status: pb.DataMovementCreateResponse_FAILED, + Message: "Error finding profile: " + err.Error(), + }, nil + } + dm.Spec.ProfileReference = corev1.ObjectReference{ + Kind: reflect.TypeOf(nnfv1alpha1.NnfDataMovementProfile{}).Name(), + Name: profile.Name, + Namespace: profile.Namespace, + } + dm.Spec.UserId = userId dm.Spec.GroupId = groupId @@ -398,6 +413,47 @@ func setUserConfig(req *pb.DataMovementCreateRequest, dm *nnfv1alpha1.NnfDataMov } } +func (s *defaultServer) getProfile(ctx context.Context, profileName string) (*nnfv1alpha1.NnfDataMovementProfile, error) { + ns := "nnf-system" + + // If a profile is named then verify that it exists. Otherwise, verify that a default profile + // can be found. + if len(profileName) == 0 { + NnfDataMovementProfiles := &nnfv1alpha1.NnfDataMovementProfileList{} + if err := s.client.List(ctx, NnfDataMovementProfiles, &client.ListOptions{Namespace: ns}); err != nil { + return nil, err + } + profilesFound := make([]string, 0, len(NnfDataMovementProfiles.Items)) + for _, profile := range NnfDataMovementProfiles.Items { + if profile.Data.Default { + objkey := client.ObjectKeyFromObject(&profile) + profilesFound = append(profilesFound, objkey.Name) + } + } + // Require that there be one and only one default. + if len(profilesFound) == 0 { + return nil, fmt.Errorf("unable to find a default NnfDataMovementProfile to use") + } else if len(profilesFound) > 1 { + return nil, fmt.Errorf("more than one default NnfDataMovementProfile found; unable to pick one: %v", profilesFound) + } + profileName = profilesFound[0] + } + + profile := &nnfv1alpha1.NnfDataMovementProfile{ + ObjectMeta: metav1.ObjectMeta{ + Name: profileName, + Namespace: ns, + }, + } + + err := s.client.Get(ctx, client.ObjectKeyFromObject(profile), profile) + if err != nil { + return nil, fmt.Errorf("unable to retrieve NnfDataMovementProfile: %s", profileName) + } + + return profile, nil +} + func getDirectiveIndexFromClientMount(object *dwsv1alpha2.ClientMount) (string, error) { // Find the DW index for our work. labels := object.GetLabels() @@ -459,7 +515,6 @@ func (s *defaultServer) createNnfDataMovement(ctx context.Context, req *pb.DataM Name: lustrefs.Name, }, }, - Profile: req.Profile, }, } @@ -489,7 +544,6 @@ func (s *defaultServer) createNnfNodeDataMovement(ctx context.Context, req *pb.D Destination: &nnfv1alpha1.NnfDataMovementSpecSourceDestination{ Path: req.Destination, }, - Profile: req.Profile, }, } diff --git a/go.mod b/go.mod index 7b0ec4b3..33599af5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf - github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240729130730-8f01fd2116ea + github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240801190336-58f2d99dd6cb github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.32.0 github.com/prometheus/client_golang v1.16.0 @@ -69,11 +69,11 @@ require ( k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 + sigs.k8s.io/yaml v1.3.0 // indirect ) require ( - github.com/DataWorkflowServices/dws v0.0.1-0.20240726140248-bd9f85356c73 + github.com/DataWorkflowServices/dws v0.0.1-0.20240801173757-1fb2188d84b9 go.openly.dev/pointy v1.3.0 ) diff --git a/go.sum b/go.sum index 23a60758..e6ae3187 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ -github.com/DataWorkflowServices/dws v0.0.1-0.20240726140248-bd9f85356c73 h1:bq1AaHhdaeuaq+ibNk/UIMExXuLicfQCir25xKHnEck= -github.com/DataWorkflowServices/dws v0.0.1-0.20240726140248-bd9f85356c73/go.mod h1:6MrEEHISskyooSKcKU6R3mFqH6Yh6KzWgajhcw2s+nM= +github.com/DataWorkflowServices/dws v0.0.1-0.20240801173757-1fb2188d84b9 h1:Jf5AxKXNxNtDC4YBbnJfpKWr4DicrEJ0aCtIgarIIqU= +github.com/DataWorkflowServices/dws v0.0.1-0.20240801173757-1fb2188d84b9/go.mod h1:6MrEEHISskyooSKcKU6R3mFqH6Yh6KzWgajhcw2s+nM= github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf h1:ArBI1LR+BBZ9lF+Aohv49RhTpmRqIXLz4L/h45qQT4k= github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf/go.mod h1:N5X1obpl0mBI0VoCJdQhv7cFXOC6g3VlXj712qWj0JE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 h1:7eT5mOVSNwtacIcGhzMAsi8EVbeS4zk9QwThG2f0GHE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5/go.mod h1:oxdwMqfttOF9dabJhqrWlirCnMk8/8eyLMwl+hducjk= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240729130730-8f01fd2116ea h1:WZCoDgPMs8+3jle4iJnx4EaPlBLd6pr2ks+o8U4yy10= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240729130730-8f01fd2116ea/go.mod h1:WBbrMgTEGvnFbbuQglDBoLl/KvcsC3F/CKY9jq5hWgU= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240801190336-58f2d99dd6cb h1:tHAn3aqU61vQ+FCo+6uLZrhamrfwq4qV5EBlBlqDOpk= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240801190336-58f2d99dd6cb/go.mod h1:uJvjwkSLrPk4A/13U/E4vnO8R+utDE/lGclsKVp/88s= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/internal/controller/datamovement_controller.go b/internal/controller/datamovement_controller.go index bf5a7e23..6396a60e 100644 --- a/internal/controller/datamovement_controller.go +++ b/internal/controller/datamovement_controller.go @@ -50,7 +50,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/yaml" dwsv1alpha2 "github.com/DataWorkflowServices/dws/api/v1alpha2" "github.com/NearNodeFlash/nnf-dm/internal/controller/metrics" @@ -61,13 +60,6 @@ import ( const ( finalizer = "dm.cray.hpe.com" - - // DM ConfigMap Info - configMapName = "nnf-dm-config" - configMapNamespace = nnfv1alpha1.DataMovementNamespace - - // DM ConfigMap Data Keys - configMapKeyData = "nnf-dm-config.yaml" ) // Regex to scrape the progress output of the `dcp` command. Example output: @@ -129,21 +121,6 @@ type dataMovementCancelContext struct { cancel context.CancelFunc } -// Configuration that matches the nnf-dm-config ConfigMap -type dmConfig struct { - Profiles map[string]dmConfigProfile `yaml:"profiles"` - ProgressIntervalSeconds int `yaml:"progressIntervalSeconds,omitempty"` -} - -// Each profile can have different settings -type dmConfigProfile struct { - Slots int `yaml:"slots,omitempty"` - MaxSlots int `yaml:"maxSlots,omitempty"` - Command string `yaml:"command"` - LogStdout bool `yaml:"logStdout"` - StoreStdout bool `yaml:"storeStdout"` -} - // Invalid error is a non-recoverable error type that implies the Data Movement resource is invalid type invalidError struct { err error @@ -161,6 +138,7 @@ func (i *invalidError) Unwrap() error { return i.err } //+kubebuilder:rbac:groups=nnf.cray.hpe.com,resources=nnfdatamovements,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=nnf.cray.hpe.com,resources=nnfdatamovements/status,verbs=get;update;patch //+kubebuilder:rbac:groups=nnf.cray.hpe.com,resources=nnfdatamovements/finalizers,verbs=update +//+kubebuilder:rbac:groups=nnf.cray.hpe.com,resources=nnfdatamovementprofiles,verbs=get;list;watch //+kubebuilder:rbac:groups=nnf.cray.hpe.com,resources=nnfstorages,verbs=get;list;watch //+kubebuilder:rbac:groups=nnf.cray.hpe.com,resources=nnfnodestorages,verbs=get;list;watch //+kubebuilder:rbac:groups=dataworkflowservices.github.io,resources=clientmounts,verbs=get;list @@ -276,29 +254,12 @@ func (r *DataMovementReconciler) Reconcile(ctx context.Context, req ctrl.Request cancel: cancel, }) - // Get DM Config map - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: configMapName, - Namespace: configMapNamespace, - }, - } - if err := r.Get(ctx, client.ObjectKeyFromObject(configMap), configMap); err != nil { - return ctrl.Result{}, dwsv1alpha2.NewResourceError("could not get data movement config map: %v", client.ObjectKeyFromObject(configMap)).WithError(err).WithMajor() - } - - cfg := dmConfig{} - if err := yaml.Unmarshal([]byte(configMap.Data[configMapKeyData]), &cfg); err != nil { - return ctrl.Result{}, dwsv1alpha2.NewResourceError("invalid data for config map: %v", client.ObjectKeyFromObject(configMap)).WithError(err).WithFatal() - } - log.Info("Using config map", "config", cfg) - - // Ensure requested DM profile exists - profile, found := cfg.Profiles[dm.Spec.Profile] - if !found { - return ctrl.Result{}, dwsv1alpha2.NewResourceError("").WithUserMessage("'%s' profile not found in config map: %v", dm.Spec.Profile, client.ObjectKeyFromObject(configMap)).WithUser().WithFatal() + // Get DM Profile + profile, err := r.getDMProfile(ctx, dm) + if err != nil { + return ctrl.Result{}, dwsv1alpha2.NewResourceError("could not get profile for data movement").WithError(err).WithMajor() } - log.Info("Using profile", "profile name", dm.Spec.Profile, "profile", profile) + log.Info("Using profile", "profile", profile) // Create the hostfile. This is needed for preparing the destination and the data movement // command itself. @@ -351,7 +312,7 @@ func (r *DataMovementReconciler) Reconcile(ctx context.Context, req ctrl.Request // While the command is running, capture and process the output. Read lines until EOF to // ensure we have the latest output. Then use the last regex match to obtain the most recent // progress. - progressCollectInterval := time.Duration(cfg.ProgressIntervalSeconds) * time.Second + progressCollectInterval := time.Duration(profile.Data.ProgressIntervalSeconds) * time.Second if progressCollectionEnabled(progressCollectInterval) { go func() { var elapsed metav1.Duration @@ -460,12 +421,12 @@ func (r *DataMovementReconciler) Reconcile(ctx context.Context, req ctrl.Request log.Info("Data movement operation completed", "cmdStatus", cmdStatus) // Profile or DM request has enabled stdout logging - if profile.LogStdout || (dm.Spec.UserConfig != nil && dm.Spec.UserConfig.LogStdout) { + if profile.Data.LogStdout || (dm.Spec.UserConfig != nil && dm.Spec.UserConfig.LogStdout) { log.Info("Data movement operation output", "output", combinedOutBuf.String()) } // Profile or DM request has enabled storing stdout - if profile.StoreStdout || (dm.Spec.UserConfig != nil && dm.Spec.UserConfig.StoreStdout) { + if profile.Data.StoreStdout || (dm.Spec.UserConfig != nil && dm.Spec.UserConfig.StoreStdout) { dm.Status.Message = combinedOutBuf.String() } } @@ -570,7 +531,28 @@ func parseDcpStats(line string, cmdStatus *nnfv1alpha1.NnfDataMovementCommandSta return nil } -func buildDMCommand(ctx context.Context, profile dmConfigProfile, hostfile string, dm *nnfv1alpha1.NnfDataMovement) ([]string, error) { +func (r *DataMovementReconciler) getDMProfile(ctx context.Context, dm *nnfv1alpha1.NnfDataMovement) (*nnfv1alpha1.NnfDataMovementProfile, error) { + + var profile *nnfv1alpha1.NnfDataMovementProfile + + if dm.Spec.ProfileReference.Kind != reflect.TypeOf(nnfv1alpha1.NnfDataMovementProfile{}).Name() { + return profile, fmt.Errorf("invalid NnfDataMovementProfile kind %s", dm.Spec.ProfileReference.Kind) + } + + profile = &nnfv1alpha1.NnfDataMovementProfile{ + ObjectMeta: metav1.ObjectMeta{ + Name: dm.Spec.ProfileReference.Name, + Namespace: dm.Spec.ProfileReference.Namespace, + }, + } + if err := r.Get(ctx, client.ObjectKeyFromObject(profile), profile); err != nil { + return nil, err + } + + return profile, nil +} + +func buildDMCommand(ctx context.Context, profile *nnfv1alpha1.NnfDataMovementProfile, hostfile string, dm *nnfv1alpha1.NnfDataMovement) ([]string, error) { log := log.FromContext(ctx) userConfig := dm.Spec.UserConfig != nil @@ -580,7 +562,7 @@ func buildDMCommand(ctx context.Context, profile dmConfigProfile, hostfile strin return []string{"true"}, nil } - cmd := profile.Command + cmd := profile.Data.Command cmd = strings.ReplaceAll(cmd, "$HOSTFILE", hostfile) cmd = strings.ReplaceAll(cmd, "$UID", fmt.Sprintf("%d", dm.Spec.UserId)) cmd = strings.ReplaceAll(cmd, "$GID", fmt.Sprintf("%d", dm.Spec.GroupId)) @@ -601,11 +583,11 @@ func buildDMCommand(ctx context.Context, profile dmConfigProfile, hostfile strin cmd = cmd[:idx] + opts + " " + cmd[idx:] } else { log.Info("spec.config.dpcOptions is set but no source path is found in the DM command", - "command", profile.Command, "DCPOptions", opts) + "command", profile.Data.Command, "DCPOptions", opts) } } else { log.Info("spec.config.dpcOptions is set but no dcp command found in the DM command", - "command", profile.Command, "DCPOptions", opts) + "command", profile.Data.Command, "DCPOptions", opts) } } } @@ -904,12 +886,12 @@ func createDestinationDir(dest string, uid, gid uint32, mpiHostfile string, log } // Create an MPI hostfile given settings from a profile and user config from the dm -func createMpiHostfile(profile dmConfigProfile, hosts []string, dm *nnfv1alpha1.NnfDataMovement) (string, error) { +func createMpiHostfile(profile *nnfv1alpha1.NnfDataMovementProfile, hosts []string, dm *nnfv1alpha1.NnfDataMovement) (string, error) { userConfig := dm.Spec.UserConfig != nil // Create MPI hostfile only if included in the provided command - slots := profile.Slots - maxSlots := profile.MaxSlots + slots := profile.Data.Slots + maxSlots := profile.Data.MaxSlots // Allow the user to override the slots and max_slots in the hostfile. if userConfig && dm.Spec.UserConfig.Slots != nil && *dm.Spec.UserConfig.Slots >= 0 { diff --git a/internal/controller/datamovement_controller_test.go b/internal/controller/datamovement_controller_test.go index b7a32bf8..9bf36ff8 100644 --- a/internal/controller/datamovement_controller_test.go +++ b/internal/controller/datamovement_controller_test.go @@ -25,6 +25,7 @@ import ( "fmt" "os" "path/filepath" + "reflect" "strings" "time" @@ -42,7 +43,6 @@ import ( "k8s.io/client-go/util/retry" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/yaml" ) // This is dumped into a temporary file and then ran as a bash script. @@ -56,10 +56,8 @@ var _ = Describe("Data Movement Test", func() { Describe("Reconciler Tests", func() { var dm *nnfv1alpha1.NnfDataMovement - var cm *corev1.ConfigMap - var dmCfg *dmConfig - var dmCfgProfile dmConfigProfile - createCm := true + var dmProfile *nnfv1alpha1.NnfDataMovementProfile + createDmProfile := true var tmpDir string var srcPath string var destPath string @@ -85,7 +83,7 @@ var _ = Describe("Data Movement Test", func() { BeforeEach(func() { var err error - createCm = true + createDmProfile = true testLabel = fmt.Sprintf("%s-%s", testLabelKey, uuid.NewString()) tmpDir, err = os.MkdirTemp("/tmp", "dm-test") @@ -104,16 +102,21 @@ var _ = Describe("Data Movement Test", func() { } k8sClient.Create(context.TODO(), ns) - // Default config map data - dmCfg = &dmConfig{ - Profiles: map[string]dmConfigProfile{ - nnfv1alpha1.DataMovementProfileDefault: { - Command: defaultCommand, + // Default DM profile + dmProfile = &nnfv1alpha1.NnfDataMovementProfile{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + Namespace: corev1.NamespaceDefault, + Labels: map[string]string{ + testLabelKey: testLabel, }, }, - ProgressIntervalSeconds: 1, + Data: nnfv1alpha1.NnfDataMovementProfileData{ + Command: defaultCommand, + ProgressIntervalSeconds: 1, + Default: true, + }, } - dmCfgProfile = dmCfg.Profiles[nnfv1alpha1.DataMovementProfileDefault] dm = &nnfv1alpha1.NnfDataMovement{ ObjectMeta: metav1.ObjectMeta{ @@ -133,37 +136,22 @@ var _ = Describe("Data Movement Test", func() { UserId: 0, GroupId: 0, Cancel: false, + ProfileReference: corev1.ObjectReference{ + Kind: reflect.TypeOf(nnfv1alpha1.NnfDataMovementProfile{}).Name(), + Name: dmProfile.Name, + Namespace: dmProfile.Namespace, + }, }, } }) JustBeforeEach(func() { - // Create CM and verify label - if createCm { - // allow test to override the values in the default cfg profile - dmCfg.Profiles[nnfv1alpha1.DataMovementProfileDefault] = dmCfgProfile - - // Convert the config to raw - b, err := yaml.Marshal(dmCfg) - Expect(err).ToNot(HaveOccurred()) - - cm = &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: configMapName, - Namespace: v1alpha1.DataMovementNamespace, - Labels: map[string]string{ - testLabelKey: testLabel, - }, - }, - Data: map[string]string{ - configMapKeyData: string(b), - }, - } - - Expect(k8sClient.Create(context.TODO(), cm)).To(Succeed()) + // Create DM Profile and verify label + if createDmProfile { + Expect(k8sClient.Create(context.TODO(), dmProfile)).To(Succeed()) Eventually(func(g Gomega) string { - g.Expect(k8sClient.Get(context.TODO(), client.ObjectKeyFromObject(cm), cm)).To(Succeed()) - return cm.Labels[testLabelKey] + g.Expect(k8sClient.Get(context.TODO(), client.ObjectKeyFromObject(dmProfile), dmProfile)).To(Succeed()) + return dmProfile.Labels[testLabelKey] }).Should(Equal(testLabel)) } @@ -186,10 +174,10 @@ var _ = Describe("Data Movement Test", func() { } // Remove configmap - if createCm { - Expect(k8sClient.Delete(context.TODO(), cm)).To(Succeed()) + if createDmProfile { + Expect(k8sClient.Delete(context.TODO(), dmProfile)).To(Succeed()) Eventually(func() error { - return k8sClient.Get(context.TODO(), client.ObjectKeyFromObject(cm), cm) + return k8sClient.Get(context.TODO(), client.ObjectKeyFromObject(dmProfile), dmProfile) }).ShouldNot(Succeed()) } @@ -199,7 +187,7 @@ var _ = Describe("Data Movement Test", func() { Context("when a data movement operation succeeds", func() { BeforeEach(func() { - dmCfgProfile.Command = "sleep 1" + dmProfile.Data.Command = "sleep 1" }) It("should have a state and status of 'Finished' and 'Success'", func() { Eventually(func(g Gomega) nnfv1alpha1.NnfDataMovementStatus { @@ -214,7 +202,7 @@ var _ = Describe("Data Movement Test", func() { Context("when a data movement command has no progress output", func() { BeforeEach(func() { - dmCfgProfile.Command = "sleep 1" + dmProfile.Data.Command = "sleep 1" }) It("CommandStatus should not have a ProgressPercentage", func() { Eventually(func(g Gomega) nnfv1alpha1.NnfDataMovementStatus { @@ -232,7 +220,7 @@ var _ = Describe("Data Movement Test", func() { Context("when the dm configmap has specified an overrideCmd", func() { BeforeEach(func() { - dmCfgProfile.Command = "ls -l" + dmProfile.Data.Command = "ls -l" }) It("should use that command instead of the default mpirun", func() { Eventually(func(g Gomega) string { @@ -242,13 +230,13 @@ var _ = Describe("Data Movement Test", func() { cmd = dm.Status.CommandStatus.Command } return cmd - }).Should(Equal(cmdBashPrefix + dmCfgProfile.Command)) + }).Should(Equal(cmdBashPrefix + dmProfile.Data.Command)) }) }) Context("when the dm configmap does not have $HOSTFILE in the command", func() { BeforeEach(func() { - dmCfgProfile.Command = "ls -l" + dmProfile.Data.Command = "ls -l" }) It("should use that command instead of the default mpirun", func() { Eventually(func(g Gomega) string { @@ -258,14 +246,14 @@ var _ = Describe("Data Movement Test", func() { cmd = dm.Status.CommandStatus.Command } return cmd - }).Should(Equal(cmdBashPrefix + dmCfgProfile.Command)) + }).Should(Equal(cmdBashPrefix + dmProfile.Data.Command)) }) }) Context("when the dm config map has specified a dmProgressInterval of less than 1s", func() { BeforeEach(func() { - dmCfgProfile.Command = "sleep .5" - dmCfg.ProgressIntervalSeconds = 0 + dmProfile.Data.Command = "sleep .5" + dmProfile.Data.ProgressIntervalSeconds = 0 }) It("the data movement should skip progress collection", func() { @@ -288,8 +276,8 @@ var _ = Describe("Data Movement Test", func() { Context("when the dm config map has specified to store Stdout", func() { output := "this is not a test" BeforeEach(func() { - dmCfgProfile.Command = "echo " + output - dmCfgProfile.StoreStdout = true + dmProfile.Data.Command = "echo " + output + dmProfile.Data.StoreStdout = true }) It("should store the output in Status.Message", func() { @@ -311,8 +299,8 @@ var _ = Describe("Data Movement Test", func() { Context("when the dm config map has specified to not store Stdout", func() { output := "this is not a test" BeforeEach(func() { - dmCfgProfile.Command = "echo " + output - dmCfgProfile.StoreStdout = false + dmProfile.Data.Command = "echo " + output + dmProfile.Data.StoreStdout = false }) It("should not store anything in Status.Message", func() { @@ -334,7 +322,7 @@ var _ = Describe("Data Movement Test", func() { Context("when the UserConfig has specified to store Stdout", func() { output := "this is not a test" BeforeEach(func() { - dmCfgProfile.Command = "echo " + output + dmProfile.Data.Command = "echo " + output dm.Spec.UserConfig = &nnfv1alpha1.NnfDataMovementConfig{ StoreStdout: true, } @@ -359,7 +347,7 @@ var _ = Describe("Data Movement Test", func() { Context("when the UserConfig has specified not to store Stdout", func() { output := "this is not a test" BeforeEach(func() { - dmCfgProfile.Command = "echo " + output + dmProfile.Data.Command = "echo " + output dm.Spec.UserConfig = &nnfv1alpha1.NnfDataMovementConfig{ StoreStdout: false, } @@ -383,7 +371,7 @@ var _ = Describe("Data Movement Test", func() { Context("when there is no dm config map", func() { BeforeEach(func() { - createCm = false + createDmProfile = false }) It("should requeue and not start running", func() { @@ -395,15 +383,27 @@ var _ = Describe("Data Movement Test", func() { }) Context("when a non-default profile is supplied (and present)", func() { - p := "test-profile" + p := &nnfv1alpha1.NnfDataMovementProfile{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-profile", + Namespace: corev1.NamespaceDefault, + }, + } cmd := "sleep .1" BeforeEach(func() { - dmCfgProfile = dmConfigProfile{ - Command: cmd, + p.Data.Command = cmd + dm.Spec.ProfileReference = corev1.ObjectReference{ + Kind: reflect.TypeOf(nnfv1alpha1.NnfDataMovementProfile{}).Name(), + Name: p.Name, + Namespace: p.Namespace, } - dmCfg.Profiles[p] = dmCfgProfile - dm.Spec.Profile = p + + Expect(k8sClient.Create(context.TODO(), p)).To(Succeed(), "create nnfDataMovementProfile") + + Eventually(func(g Gomega) { + g.Expect(k8sClient.Get(context.TODO(), client.ObjectKeyFromObject(p), p)).To(Succeed()) + }, "3s", "1s").Should(Succeed(), "wait for create of NnfDataMovementProfile") }) It("should use that profile to perform data movement", func() { @@ -417,21 +417,33 @@ var _ = Describe("Data Movement Test", func() { })) By("verify that profile is used") - Expect(dm.Spec.Profile).To(Equal(p)) + Expect(dm.Spec.ProfileReference).To(MatchFields(IgnoreExtras, + Fields{ + "Kind": Equal(reflect.TypeOf(nnfv1alpha1.NnfDataMovementProfile{}).Name()), + "Name": Equal(p.Name), + "Namespace": Equal(p.Namespace), + }, + )) Expect(dm.Status.CommandStatus.Command).To(Equal(cmdBashPrefix + cmd)) }) }) Context("when a non-default profile is supplied (and NOT present)", func() { - m := "missing-test-profile" + m := &nnfv1alpha1.NnfDataMovementProfile{ + ObjectMeta: metav1.ObjectMeta{ + Name: "missing-test-profile", + Namespace: corev1.NamespaceDefault, + }, + } cmd := "sleep .1" BeforeEach(func() { - dmCfgProfile = dmConfigProfile{ - Command: cmd, + m.Data.Command = cmd + dm.Spec.ProfileReference = corev1.ObjectReference{ + Kind: reflect.TypeOf(nnfv1alpha1.NnfDataMovementProfile{}).Name(), + Name: m.Name, + Namespace: m.Namespace, } - dmCfg.Profiles["test-profile"] = dmCfgProfile - dm.Spec.Profile = m }) It("should use that profile to perform data movement and fail", func() { @@ -445,13 +457,19 @@ var _ = Describe("Data Movement Test", func() { })) By("verify that profile is used") - Expect(dm.Spec.Profile).To(Equal(m)) + Expect(dm.Spec.ProfileReference).To(MatchFields(IgnoreExtras, + Fields{ + "Kind": Equal(reflect.TypeOf(nnfv1alpha1.NnfDataMovementProfile{}).Name()), + "Name": Equal(m.Name), + "Namespace": Equal(m.Namespace), + }, + )) }) }) Context("when a data movement command fails", func() { BeforeEach(func() { - dmCfgProfile.Command = "false" + dmProfile.Data.Command = "false" }) It("should have a State/Status of 'Finished'/'Failed'", func() { Eventually(func(g Gomega) nnfv1alpha1.NnfDataMovementStatus { @@ -470,7 +488,7 @@ var _ = Describe("Data Movement Test", func() { BeforeEach(func() { // Set cancel on creation so that data movement doesn't start dm.Spec.Cancel = true - dmCfgProfile.Command = "false" + dmProfile.Data.Command = "false" }) It("should have a State/Status of 'Finished'/'Cancelled' and StartTime/EndTime should be set to now", func() { @@ -530,14 +548,14 @@ var _ = Describe("Data Movement Test", func() { Expect(err).ToNot(HaveOccurred()) commandWithArgs = fmt.Sprintf("/bin/bash %s %d %f", scriptFilePath, commandDuration, commandIntervalInSec) - dmCfgProfile.Command = commandWithArgs + dmProfile.Data.Command = commandWithArgs }) It("should update progress by parsing the output of the command", func() { startTime := metav1.NowMicro() - Expect(k8sClient.Get(context.TODO(), client.ObjectKeyFromObject(cm), cm)).To(Succeed()) - Expect(dmCfgProfile.Command).To(Equal(commandWithArgs)) + Expect(k8sClient.Get(context.TODO(), client.ObjectKeyFromObject(dmProfile), dmProfile)).To(Succeed()) + Expect(dmProfile.Data.Command).To(Equal(commandWithArgs)) By("ensuring that we do not have a progress to start") Eventually(func(g Gomega) *int32 { @@ -614,8 +632,8 @@ var _ = Describe("Data Movement Test", func() { _, err := os.Stat(scriptFilePath) Expect(err).ToNot(HaveOccurred()) - dmCfgProfile.Command = fmt.Sprintf("/bin/bash %s 10 .25", scriptFilePath) - dmCfg.ProgressIntervalSeconds = 1 + dmProfile.Data.Command = fmt.Sprintf("/bin/bash %s 10 .25", scriptFilePath) + dmProfile.Data.ProgressIntervalSeconds = 1 }) It("LastMessage should not include multiple lines of output", func() { @@ -635,7 +653,7 @@ var _ = Describe("Data Movement Test", func() { Context("when a data movement operation is cancelled", func() { BeforeEach(func() { - dmCfgProfile.Command = "sleep 5" + dmProfile.Data.Command = "sleep 5" }) It("should have a state and status of 'Finished' and 'Cancelled'", func() { By("ensuring the data movement started") @@ -737,11 +755,10 @@ var _ = Describe("Data Movement Test", func() { } When("$HOSTFILE is present", func() { It("should create the hostfile", func() { - profile := dmConfigProfile{ - Command: "mpirun --hostfile $HOSTFILE dcp src dest", - } + profile := nnfv1alpha1.NnfDataMovementProfile{} + profile.Data.Command = "mpirun --hostfile $HOSTFILE dcp src dest" - hostfile, err := createMpiHostfile(profile, hosts, &dm) + hostfile, err := createMpiHostfile(&profile, hosts, &dm) Expect(err).ToNot(HaveOccurred()) Expect(len(hostfile)).Should((BeNumerically(">", 0))) info, err := os.Stat(hostfile) @@ -773,9 +790,9 @@ var _ = Describe("Data Movement Test", func() { When("DCPOptions are specified", func() { It("should inject the extra options before the $SRC argument to dcp", func() { - profile := dmConfigProfile{ - Command: defaultCommand, - } + profile := nnfv1alpha1.NnfDataMovementProfile{} + profile.Data.Command = defaultCommand + dm.Spec.UserConfig = &nnfv1alpha1.NnfDataMovementConfig{ DCPOptions: "--extra opts", } @@ -783,7 +800,7 @@ var _ = Describe("Data Movement Test", func() { "mpirun --allow-run-as-root --hostfile /tmp/hostfile dcp --progress 1 --uid %d --gid %d --extra opts %s %s", expectedUid, expectedGid, srcPath, destPath) - cmd, err := buildDMCommand(context.TODO(), profile, "/tmp/hostfile", &dm) + cmd, err := buildDMCommand(context.TODO(), &profile, "/tmp/hostfile", &dm) Expect(err).ToNot(HaveOccurred()) Expect(strings.Join(cmd, " ")).Should(MatchRegexp(expectedCmdRegex)) }) @@ -794,17 +811,19 @@ var _ = Describe("Data Movement Test", func() { func(numSlots *int) { profileSlots, profileMaxSlots := 3, 8 - profile := dmConfigProfile{ - Command: defaultCommand, - Slots: profileSlots, - MaxSlots: profileMaxSlots, + profile := nnfv1alpha1.NnfDataMovementProfile{ + Data: nnfv1alpha1.NnfDataMovementProfileData{ + Command: defaultCommand, + Slots: profileSlots, + MaxSlots: profileMaxSlots, + }, } dm.Spec.UserConfig = &nnfv1alpha1.NnfDataMovementConfig{ Slots: numSlots, MaxSlots: numSlots, } - hostfilePath, err := createMpiHostfile(profile, hosts, &dm) + hostfilePath, err := createMpiHostfile(&profile, hosts, &dm) Expect(err).ToNot(HaveOccurred()) Expect(hostfilePath).ToNot(BeEmpty()) DeferCleanup(func() { diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/resource.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/resource.go index 62157d6d..95d8671f 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/resource.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/resource.go @@ -34,7 +34,7 @@ const ( ) // ResourceStatus is the enumeration of the status of a DWS resource -// +kubebuilder:validation:Enum:=Starting;Ready;Disabled;NotPresent;Offline;Failed;Degraded;Unknown +// +kubebuilder:validation:Enum:=Starting;Ready;Disabled;NotPresent;Offline;Failed;Degraded;Drained;Unknown type ResourceStatus string const ( @@ -56,7 +56,7 @@ const ( NotPresentStatus ResourceStatus = "NotPresent" // Offline means the resource is offline and cannot be communicated with. This differs - // fro the NotPresent state in that the resource is known to exist. + // from the NotPresent state in that the resource is known to exist. OfflineStatus ResourceStatus = "Offline" // Failed means the resource has failed during startup or execution. @@ -66,6 +66,9 @@ const ( // recovery actions may alleviate a degraded status. DegradedStatus ResourceStatus = "Degraded" + // Drained means the resource has had its pods drained from the node. + DrainedStatus ResourceStatus = "Drained" + // Unknown means the resource status is unknown. UnknownStatus ResourceStatus = "Unknown" ) diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go index 2a37a77d..a561ba9c 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_datamovement_types.go @@ -32,9 +32,8 @@ const ( // NNF Node Name as the namespace. DataMovementNamespace = "nnf-dm-system" - // The name of the default profile stored in the nnf-dm-config ConfigMap that is used to - // configure Data Movement. - DataMovementProfileDefault = "default" + // The namespace for NnfDataMovementProfiles that are not pinned. + DataMovementProfileNamespace = "nnf-system" ) // NnfDataMovementSpec defines the desired state of NnfDataMovement @@ -62,14 +61,13 @@ type NnfDataMovementSpec struct { // +kubebuilder:default:=false Cancel bool `json:"cancel,omitempty"` - // Profile specifies the name of profile in the nnf-dm-config ConfigMap to be used for - // configuring data movement. Defaults to the default profile. - // +kubebuilder:default:=default - Profile string `json:"profile,omitempty"` + // ProfileReference is an object reference to an NnfDataMovementProfile that is used to + // configure data movement. If empty, the default profile is used. + ProfileReference corev1.ObjectReference `json:"profileReference,omitempty"` // User defined configuration on how data movement should be performed. This overrides the - // configuration defined in the nnf-dm-config ConfigMap. These values are typically set by the - // Copy Offload API. + // configuration defined in the supplied ProfileReference/NnfDataMovementProfile. These values + // are typically set by the Copy Offload API. UserConfig *NnfDataMovementConfig `json:"userConfig,omitempty"` } @@ -109,11 +107,11 @@ type NnfDataMovementConfig struct { StoreStdout bool `json:"storeStdout,omitempty"` // The number of slots specified in the MPI hostfile. A value of 0 disables the use of slots in - // the hostfile. Nil will defer to the value specified in the nnf-dm-config ConfigMap. + // the hostfile. Nil will defer to the value specified in the NnfDataMovementProfile. Slots *int `json:"slots,omitempty"` // The number of max_slots specified in the MPI hostfile. A value of 0 disables the use of slots - // in the hostfile. Nil will defer to the value specified in the nnf-dm-config ConfigMap. + // in the hostfile. Nil will defer to the value specified in the NnfDataMovementProfile. MaxSlots *int `json:"maxSlots,omitempty"` } diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go new file mode 100644 index 00000000..fec73ad5 --- /dev/null +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go @@ -0,0 +1,100 @@ +/* + * Copyright 2024 Hewlett Packard Enterprise Development LP + * Other additional copyright holders may be indicated within. + * + * The entirety of this work is 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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// NnfDataMovementProfileData defines the desired state of NnfDataMovementProfile +type NnfDataMovementProfileData struct { + + // Default is true if this instance is the default resource to use + // +kubebuilder:default:=false + Default bool `json:"default,omitempty"` + + // Pinned is true if this instance is an immutable copy + // +kubebuilder:default:=false + Pinned bool `json:"pinned,omitempty"` + + // Slots is the number of slots specified in the MPI hostfile. A value less than 1 disables the + // use of slots in the hostfile. + // +kubebuilder:default:=8 + Slots int `json:"slots"` + + // MaxSlots is the number of max_slots specified in the MPI hostfile. A value less than 1 + // disables the use of max_slots in the hostfile. + // +kubebuilder:default:=0 + MaxSlots int `json:"maxSlots"` + + // Command to execute to perform data movement. $VARS are replaced by the nnf software and must + // be present in the command. + // Available $VARS: + // HOSTFILE: hostfile that is created and used for mpirun. Contains a list of hosts and the + // slots/max_slots for each host. This hostfile is created at `/tmp//hostfile` + // UID: User ID that is inherited from the Workflow + // GID: Group ID that is inherited from the Workflow + // SRC: source for the data movement + // DEST destination for the data movement + // +kubebuilder:default:="ulimit -n 2048 && mpirun --allow-run-as-root --hostfile $HOSTFILE dcp --progress 1 --uid $UID --gid $GID $SRC $DEST" + Command string `json:"command"` + + // If true, enable the command's stdout to be saved in the log when the command completes + // successfully. On failure, the output is always logged. + // +kubebuilder:default:=false + LogStdout bool `json:"logStdout,omitempty"` + + // Similar to logStdout, store the command's stdout in Status.Message when the command completes + // successfully. On failure, the output is always stored. + // +kubebuilder:default:=false + StoreStdout bool `json:"storeStdout,omitempty"` + + // NnfDataMovement resources have the ability to collect and store the progress percentage and the + // last few lines of output in the CommandStatus field. This number is used for the interval to collect + // the progress data. `dcp --progress N` must be included in the data movement command in order for + // progress to be collected. A value less than 1 disables this functionality. + // +kubebuilder:default:=5 + ProgressIntervalSeconds int `json:"progressIntervalSeconds,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:printcolumn:name="DEFAULT",type="boolean",JSONPath=".data.default",description="True if this is the default instance" +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" + +// NnfDataMovementProfile is the Schema for the nnfdatamovementprofiles API +type NnfDataMovementProfile struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Data NnfDataMovementProfileData `json:"data,omitempty"` +} + +// +kubebuilder:object:root=true + +// NnfDataMovementProfileList contains a list of NnfDataMovementProfile +type NnfDataMovementProfileList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NnfDataMovementProfile `json:"items"` +} + +func init() { + SchemeBuilder.Register(&NnfDataMovementProfile{}, &NnfDataMovementProfileList{}) +} diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go index e0f2a631..29c36ccf 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go @@ -477,6 +477,79 @@ func (in *NnfDataMovementManagerStatus) DeepCopy() *NnfDataMovementManagerStatus return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NnfDataMovementProfile) DeepCopyInto(out *NnfDataMovementProfile) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Data = in.Data +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfDataMovementProfile. +func (in *NnfDataMovementProfile) DeepCopy() *NnfDataMovementProfile { + if in == nil { + return nil + } + out := new(NnfDataMovementProfile) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NnfDataMovementProfile) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NnfDataMovementProfileData) DeepCopyInto(out *NnfDataMovementProfileData) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfDataMovementProfileData. +func (in *NnfDataMovementProfileData) DeepCopy() *NnfDataMovementProfileData { + if in == nil { + return nil + } + out := new(NnfDataMovementProfileData) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NnfDataMovementProfileList) DeepCopyInto(out *NnfDataMovementProfileList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NnfDataMovementProfile, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfDataMovementProfileList. +func (in *NnfDataMovementProfileList) DeepCopy() *NnfDataMovementProfileList { + if in == nil { + return nil + } + out := new(NnfDataMovementProfileList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NnfDataMovementProfileList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NnfDataMovementSpec) DeepCopyInto(out *NnfDataMovementSpec) { *out = *in @@ -490,6 +563,7 @@ func (in *NnfDataMovementSpec) DeepCopyInto(out *NnfDataMovementSpec) { *out = new(NnfDataMovementSpecSourceDestination) **out = **in } + out.ProfileReference = in.ProfileReference if in.UserConfig != nil { in, out := &in.UserConfig, &out.UserConfig *out = new(NnfDataMovementConfig) diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml new file mode 100644 index 00000000..e947df4e --- /dev/null +++ b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml @@ -0,0 +1,114 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: nnfdatamovementprofiles.nnf.cray.hpe.com +spec: + group: nnf.cray.hpe.com + names: + kind: NnfDataMovementProfile + listKind: NnfDataMovementProfileList + plural: nnfdatamovementprofiles + singular: nnfdatamovementprofile + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: True if this is the default instance + jsonPath: .data.default + name: DEFAULT + type: boolean + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NnfDataMovementProfile is the Schema for the nnfdatamovementprofiles + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + data: + description: NnfDataMovementProfileData defines the desired state of NnfDataMovementProfile + properties: + command: + default: ulimit -n 2048 && mpirun --allow-run-as-root --hostfile $HOSTFILE + dcp --progress 1 --uid $UID --gid $GID $SRC $DEST + description: |- + Command to execute to perform data movement. $VARS are replaced by the nnf software and must + be present in the command. + Available $VARS: + HOSTFILE: hostfile that is created and used for mpirun. Contains a list of hosts and the + slots/max_slots for each host. This hostfile is created at `/tmp//hostfile` + UID: User ID that is inherited from the Workflow + GID: Group ID that is inherited from the Workflow + SRC: source for the data movement + DEST destination for the data movement + type: string + default: + default: false + description: Default is true if this instance is the default resource + to use + type: boolean + logStdout: + default: false + description: |- + If true, enable the command's stdout to be saved in the log when the command completes + successfully. On failure, the output is always logged. + type: boolean + maxSlots: + default: 0 + description: |- + MaxSlots is the number of max_slots specified in the MPI hostfile. A value less than 1 + disables the use of max_slots in the hostfile. + type: integer + pinned: + default: false + description: Pinned is true if this instance is an immutable copy + type: boolean + progressIntervalSeconds: + default: 5 + description: |- + NnfDataMovement resources have the ability to collect and store the progress percentage and the + last few lines of output in the CommandStatus field. This number is used for the interval to collect + the progress data. `dcp --progress N` must be included in the data movement command in order for + progress to be collected. A value less than 1 disables this functionality. + type: integer + slots: + default: 8 + description: |- + Slots is the number of slots specified in the MPI hostfile. A value less than 1 disables the + use of slots in the hostfile. + type: integer + storeStdout: + default: false + description: |- + Similar to logStdout, store the command's stdout in Status.Message when the command completes + successfully. On failure, the output is always stored. + type: boolean + required: + - command + - maxSlots + - slots + type: object + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + type: object + served: true + storage: true + subresources: {} diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovements.yaml b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovements.yaml index d4e1660b..e9f001d7 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovements.yaml +++ b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovements.yaml @@ -121,12 +121,52 @@ spec: the data movement operation. format: int32 type: integer - profile: - default: default + profileReference: description: |- - Profile specifies the name of profile in the nnf-dm-config ConfigMap to be used for - configuring data movement. Defaults to the default profile. - type: string + ProfileReference is an object reference to an NnfDataMovementProfile that is used to + configure data movement. If empty, the default profile is used. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic source: description: Source describes the source of the data movement operation properties: @@ -184,8 +224,8 @@ spec: userConfig: description: |- User defined configuration on how data movement should be performed. This overrides the - configuration defined in the nnf-dm-config ConfigMap. These values are typically set by the - Copy Offload API. + configuration defined in the supplied ProfileReference/NnfDataMovementProfile. These values + are typically set by the Copy Offload API. properties: dcpOptions: description: Extra options to pass to the dcp command (used to @@ -207,12 +247,12 @@ spec: maxSlots: description: |- The number of max_slots specified in the MPI hostfile. A value of 0 disables the use of slots - in the hostfile. Nil will defer to the value specified in the nnf-dm-config ConfigMap. + in the hostfile. Nil will defer to the value specified in the NnfDataMovementProfile. type: integer slots: description: |- The number of slots specified in the MPI hostfile. A value of 0 disables the use of slots in - the hostfile. Nil will defer to the value specified in the nnf-dm-config ConfigMap. + the hostfile. Nil will defer to the value specified in the NnfDataMovementProfile. type: integer storeStdout: default: false @@ -289,7 +329,7 @@ spec: type: integer progress: description: |- - Progress refects the progress of the underlying data movement command as captured from + ProgressPercentage refects the progress of the underlying data movement command as captured from standard output. A best effort is made to parse the command output as a percentage. If no progress has yet to be measured than this field is omitted. If the latest command output does not contain a valid percentage, then the value is unchanged from the previously parsed value. diff --git a/vendor/modules.txt b/vendor/modules.txt index 94b350c2..5d96ddca 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/DataWorkflowServices/dws v0.0.1-0.20240726140248-bd9f85356c73 +# github.com/DataWorkflowServices/dws v0.0.1-0.20240801173757-1fb2188d84b9 ## explicit; go 1.21 github.com/DataWorkflowServices/dws/api/v1alpha2 github.com/DataWorkflowServices/dws/utils/dwdparse @@ -10,7 +10,7 @@ github.com/NearNodeFlash/lustre-fs-operator/config/crd/bases # github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 ## explicit; go 1.19 github.com/NearNodeFlash/nnf-ec/pkg/rfsf/pkg/models -# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240729130730-8f01fd2116ea +# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240801190336-58f2d99dd6cb ## explicit; go 1.21 github.com/NearNodeFlash/nnf-sos/api/v1alpha1 github.com/NearNodeFlash/nnf-sos/config/crd/bases From d7b12ce75d9d4d4e38f7441c78adb59af1af919d Mon Sep 17 00:00:00 2001 From: Dean Roehrich Date: Mon, 12 Aug 2024 12:56:01 -0500 Subject: [PATCH 07/13] Handle case mismatch warning for FROM and AS (#194) Signed-off-by: Dean Roehrich --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index c00ac595..56a842e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ ARG NNFMFU_TAG_BASE=ghcr.io/nearnodeflash/nnf-mfu ARG NNFMFU_VERSION=master # Build the manager binary -FROM golang:1.21-alpine as builder +FROM golang:1.21-alpine AS builder ARG TARGETARCH ARG TARGETOS @@ -48,7 +48,7 @@ COPY internal/ internal/ RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go ############################################################################### -FROM builder as testing +FROM builder AS testing WORKDIR /workspace From 9fecb2220a74fc25cccbb9617bf34fb44987f043 Mon Sep 17 00:00:00 2001 From: Dean Roehrich Date: Mon, 12 Aug 2024 14:42:57 -0500 Subject: [PATCH 08/13] Re-vendor nnf-sos datamovementprofile changes (#195) Signed-off-by: Dean Roehrich --- go.mod | 2 +- go.sum | 4 +- .../v1alpha1/nnfcontainerprofile_webhook.go | 4 +- .../v1alpha1/nnfdatamovementprofile_types.go | 13 +- .../nnfdatamovementprofile_webhook.go | 116 ++++++++++++++++++ .../api/v1alpha1/nnfstorageprofile_webhook.go | 10 +- ....cray.hpe.com_nnfdatamovementprofiles.yaml | 13 +- vendor/modules.txt | 2 +- 8 files changed, 140 insertions(+), 24 deletions(-) create mode 100644 vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_webhook.go diff --git a/go.mod b/go.mod index 33599af5..c966fd16 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf - github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240801190336-58f2d99dd6cb + github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240812175705-2729a8a1ebc6 github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.32.0 github.com/prometheus/client_golang v1.16.0 diff --git a/go.sum b/go.sum index e6ae3187..5cbc7145 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf/go.mod h1:N5X1obpl0mBI0VoCJdQhv7cFXOC6g3VlXj712qWj0JE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 h1:7eT5mOVSNwtacIcGhzMAsi8EVbeS4zk9QwThG2f0GHE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5/go.mod h1:oxdwMqfttOF9dabJhqrWlirCnMk8/8eyLMwl+hducjk= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240801190336-58f2d99dd6cb h1:tHAn3aqU61vQ+FCo+6uLZrhamrfwq4qV5EBlBlqDOpk= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240801190336-58f2d99dd6cb/go.mod h1:uJvjwkSLrPk4A/13U/E4vnO8R+utDE/lGclsKVp/88s= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240812175705-2729a8a1ebc6 h1:wrPP0qBdfmnfVOxAtoR/Ud9C8qrGDVa4AEfZQIm9t6I= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240812175705-2729a8a1ebc6/go.mod h1:uJvjwkSLrPk4A/13U/E4vnO8R+utDE/lGclsKVp/88s= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfcontainerprofile_webhook.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfcontainerprofile_webhook.go index 7a8d8450..c6b94805 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfcontainerprofile_webhook.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfcontainerprofile_webhook.go @@ -34,7 +34,7 @@ import ( ) // log is for logging in this package. -var nnfcontainerprofilelog = logf.Log.WithName("nnfcontainerprofile-resource") +var nnfcontainerprofilelog = logf.Log.WithName("nnfcontainerprofile") func (r *NnfContainerProfile) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). @@ -42,7 +42,6 @@ func (r *NnfContainerProfile) SetupWebhookWithManager(mgr ctrl.Manager) error { Complete() } -// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. //+kubebuilder:webhook:path=/validate-nnf-cray-hpe-com-v1alpha1-nnfcontainerprofile,mutating=false,failurePolicy=fail,sideEffects=None,groups=nnf.cray.hpe.com,resources=nnfcontainerprofiles,verbs=create;update,versions=v1alpha1,name=vnnfcontainerprofile.kb.io,admissionReviewVersions=v1 var _ webhook.Validator = &NnfContainerProfile{} @@ -162,6 +161,5 @@ func (r *NnfContainerProfile) validateContent() error { // ValidateDelete implements webhook.Validator so a webhook will be registered for the type func (r *NnfContainerProfile) ValidateDelete() (admission.Warnings, error) { - nnfcontainerprofilelog.Info("validate delete", "name", r.Name) return nil, nil } diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go index fec73ad5..65b0c59d 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go @@ -34,14 +34,16 @@ type NnfDataMovementProfileData struct { // +kubebuilder:default:=false Pinned bool `json:"pinned,omitempty"` - // Slots is the number of slots specified in the MPI hostfile. A value less than 1 disables the - // use of slots in the hostfile. + // Slots is the number of slots specified in the MPI hostfile. A value of 0 disables the use of + // slots in the hostfile. // +kubebuilder:default:=8 + // +kubebuilder:validation:Minimum:=0 Slots int `json:"slots"` - // MaxSlots is the number of max_slots specified in the MPI hostfile. A value less than 1 - // disables the use of max_slots in the hostfile. + // MaxSlots is the number of max_slots specified in the MPI hostfile. A value of 0 disables the + // use of max_slots in the hostfile. // +kubebuilder:default:=0 + // +kubebuilder:validation:Minimum:=0 MaxSlots int `json:"maxSlots"` // Command to execute to perform data movement. $VARS are replaced by the nnf software and must @@ -69,8 +71,9 @@ type NnfDataMovementProfileData struct { // NnfDataMovement resources have the ability to collect and store the progress percentage and the // last few lines of output in the CommandStatus field. This number is used for the interval to collect // the progress data. `dcp --progress N` must be included in the data movement command in order for - // progress to be collected. A value less than 1 disables this functionality. + // progress to be collected. A value of 0 disables this functionality. // +kubebuilder:default:=5 + // +kubebuilder:validation:Minimum:=0 ProgressIntervalSeconds int `json:"progressIntervalSeconds,omitempty"` } diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_webhook.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_webhook.go new file mode 100644 index 00000000..55f785bf --- /dev/null +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_webhook.go @@ -0,0 +1,116 @@ +/* + * Copyright 2024 Hewlett Packard Enterprise Development LP + * Other additional copyright holders may be indicated within. + * + * The entirety of this work is 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 v1alpha1 + +import ( + "fmt" + "os" + "reflect" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// log is for logging in this package. +var nnfdatamovementprofilelog = logf.Log.WithName("nnfdatamovementprofile") + +// SetupWebhookWithManager will setup the manager to manage the webhooks +func (r *NnfDataMovementProfile) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// +kubebuilder:webhook:path=/validate-nnf-cray-hpe-com-v1alpha1-nnfdatamovementprofile,mutating=false,failurePolicy=fail,sideEffects=None,groups=nnf.cray.hpe.com,resources=nnfdatamovementprofiles,verbs=create;update,versions=v1alpha1,name=vnnfdatamovementprofile.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &NnfDataMovementProfile{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *NnfDataMovementProfile) ValidateCreate() (admission.Warnings, error) { + nnfdatamovementprofilelog.Info("validate create", "name", r.Name) + + // If it's not pinned, then it's being made available for users to select + // and it must be in the correct namespace. + profileNamespace := os.Getenv("NNF_DM_PROFILE_NAMESPACE") + if !r.Data.Pinned && r.GetNamespace() != profileNamespace { + err := fmt.Errorf("incorrect namespace for profile that is intended to be selected by users; the namespace should be '%s'", profileNamespace) + nnfdatamovementprofilelog.Error(err, "invalid") + return nil, err + } + + if err := r.validateContent(); err != nil { + nnfdatamovementprofilelog.Error(err, "invalid NnfDataMovementProfile resource") + return nil, err + } + + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *NnfDataMovementProfile) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + nnfdatamovementprofilelog.Info("validate update", "name", r.Name) + + obj := old.(*NnfDataMovementProfile) + if obj.Data.Pinned != r.Data.Pinned { + err := fmt.Errorf("the pinned flag is immutable") + nnfdatamovementprofilelog.Error(err, "invalid") + return nil, err + } + if obj.Data.Pinned { + // Allow metadata to be updated, for things like finalizers, + // ownerReferences, and labels, but do not allow Data to be + // updated. + if !reflect.DeepEqual(r.Data, obj.Data) { + msg := "update on pinned resource not allowed" + err := fmt.Errorf(msg) + nnfdatamovementprofilelog.Error(err, "invalid") + return nil, err + } + } + + if err := r.validateContent(); err != nil { + nnfdatamovementprofilelog.Error(err, "invalid NnfDataMovementProfile resource") + return nil, err + } + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *NnfDataMovementProfile) ValidateDelete() (admission.Warnings, error) { + return nil, nil +} + +func (r *NnfDataMovementProfile) validateContent() error { + + if r.Data.Default && r.Data.Pinned { + return fmt.Errorf("the NnfDataMovementProfile cannot be both default and pinned") + } + + if r.Data.Slots > 0 && r.Data.MaxSlots > 0 { + if r.Data.Slots > r.Data.MaxSlots { + return fmt.Errorf("both Slots and MaxSlots are provided and Slots (%d) is more than MaxSlots (%d)", r.Data.Slots, r.Data.MaxSlots) + } + } + + return nil +} diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfstorageprofile_webhook.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfstorageprofile_webhook.go index ad906c50..9ff9d03a 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfstorageprofile_webhook.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfstorageprofile_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 Hewlett Packard Enterprise Development LP + * Copyright 2022-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -33,7 +33,7 @@ import ( ) // log is for logging in this package. -var nnfstorageprofilelog = logf.Log.WithName("nnfstorageprofile-resource") +var nnfstorageprofilelog = logf.Log.WithName("nnfstorageprofile") func (r *NnfStorageProfile) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). @@ -41,7 +41,6 @@ func (r *NnfStorageProfile) SetupWebhookWithManager(mgr ctrl.Manager) error { Complete() } -// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. //+kubebuilder:webhook:path=/validate-nnf-cray-hpe-com-v1alpha1-nnfstorageprofile,mutating=false,failurePolicy=fail,sideEffects=None,groups=nnf.cray.hpe.com,resources=nnfstorageprofiles,verbs=create;update,versions=v1alpha1,name=vnnfstorageprofile.kb.io,admissionReviewVersions=v1 var _ webhook.Validator = &NnfStorageProfile{} @@ -72,7 +71,7 @@ func (r *NnfStorageProfile) ValidateUpdate(old runtime.Object) (admission.Warnin obj := old.(*NnfStorageProfile) if obj.Data.Pinned != r.Data.Pinned { err := fmt.Errorf("the pinned flag is immutable") - nnfcontainerprofilelog.Error(err, "invalid") + nnfstorageprofilelog.Error(err, "invalid") return nil, err } if obj.Data.Pinned { @@ -96,9 +95,6 @@ func (r *NnfStorageProfile) ValidateUpdate(old runtime.Object) (admission.Warnin // ValidateDelete implements webhook.Validator so a webhook will be registered for the type func (r *NnfStorageProfile) ValidateDelete() (admission.Warnings, error) { - //nnfstorageprofilelog.V(1).Info("validate delete", "name", r.Name) - - // TODO(user): fill in your validation logic upon object deletion. return nil, nil } diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml index e947df4e..554ca460 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml +++ b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml @@ -66,8 +66,9 @@ spec: maxSlots: default: 0 description: |- - MaxSlots is the number of max_slots specified in the MPI hostfile. A value less than 1 - disables the use of max_slots in the hostfile. + MaxSlots is the number of max_slots specified in the MPI hostfile. A value of 0 disables the + use of max_slots in the hostfile. + minimum: 0 type: integer pinned: default: false @@ -79,13 +80,15 @@ spec: NnfDataMovement resources have the ability to collect and store the progress percentage and the last few lines of output in the CommandStatus field. This number is used for the interval to collect the progress data. `dcp --progress N` must be included in the data movement command in order for - progress to be collected. A value less than 1 disables this functionality. + progress to be collected. A value of 0 disables this functionality. + minimum: 0 type: integer slots: default: 8 description: |- - Slots is the number of slots specified in the MPI hostfile. A value less than 1 disables the - use of slots in the hostfile. + Slots is the number of slots specified in the MPI hostfile. A value of 0 disables the use of + slots in the hostfile. + minimum: 0 type: integer storeStdout: default: false diff --git a/vendor/modules.txt b/vendor/modules.txt index 5d96ddca..291c8434 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,7 +10,7 @@ github.com/NearNodeFlash/lustre-fs-operator/config/crd/bases # github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 ## explicit; go 1.19 github.com/NearNodeFlash/nnf-ec/pkg/rfsf/pkg/models -# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240801190336-58f2d99dd6cb +# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240812175705-2729a8a1ebc6 ## explicit; go 1.21 github.com/NearNodeFlash/nnf-sos/api/v1alpha1 github.com/NearNodeFlash/nnf-sos/config/crd/bases From 732134f5903852ff03fe5c2fd4feb1f635e54ed2 Mon Sep 17 00:00:00 2001 From: Blake Devcich Date: Mon, 19 Aug 2024 13:38:16 -0500 Subject: [PATCH 09/13] Update nnf-sos modules Signed-off-by: Blake Devcich --- go.mod | 2 +- go.sum | 4 +- .../nnf-sos/api/v1alpha1/nnf_lustre_mgt.go | 107 +++++++ .../v1alpha1/nnf_node_block_storage_types.go | 5 + .../nnf-sos/api/v1alpha1/nnf_storage_types.go | 20 +- .../api/v1alpha1/zz_generated.deepcopy.go | 145 +++++++++ .../bases/nnf.cray.hpe.com_nnflustremgts.yaml | 287 ++++++++++++++++++ ...nnf.cray.hpe.com_nnfnodeblockstorages.yaml | 7 + .../bases/nnf.cray.hpe.com_nnfstorages.yaml | 56 +++- vendor/modules.txt | 2 +- 10 files changed, 620 insertions(+), 15 deletions(-) create mode 100644 vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_lustre_mgt.go create mode 100644 vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnflustremgts.yaml diff --git a/go.mod b/go.mod index c966fd16..f2542c88 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf - github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240812175705-2729a8a1ebc6 + github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240816013414-a2246392cd0a github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.32.0 github.com/prometheus/client_golang v1.16.0 diff --git a/go.sum b/go.sum index 5cbc7145..12847922 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf/go.mod h1:N5X1obpl0mBI0VoCJdQhv7cFXOC6g3VlXj712qWj0JE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 h1:7eT5mOVSNwtacIcGhzMAsi8EVbeS4zk9QwThG2f0GHE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5/go.mod h1:oxdwMqfttOF9dabJhqrWlirCnMk8/8eyLMwl+hducjk= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240812175705-2729a8a1ebc6 h1:wrPP0qBdfmnfVOxAtoR/Ud9C8qrGDVa4AEfZQIm9t6I= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240812175705-2729a8a1ebc6/go.mod h1:uJvjwkSLrPk4A/13U/E4vnO8R+utDE/lGclsKVp/88s= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240816013414-a2246392cd0a h1:h08LssHEqjca6mWLHjEPwoozQ01VAslvmUI2aUzTQIM= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240816013414-a2246392cd0a/go.mod h1:uJvjwkSLrPk4A/13U/E4vnO8R+utDE/lGclsKVp/88s= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_lustre_mgt.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_lustre_mgt.go new file mode 100644 index 00000000..0d2f27e1 --- /dev/null +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_lustre_mgt.go @@ -0,0 +1,107 @@ +/* + * Copyright 2024 Hewlett Packard Enterprise Development LP + * Other additional copyright holders may be indicated within. + * + * The entirety of this work is 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 v1alpha1 + +import ( + dwsv1alpha2 "github.com/DataWorkflowServices/dws/api/v1alpha2" + "github.com/DataWorkflowServices/dws/utils/updater" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// NnfLustreMGTSpec defines the desired state of NnfLustreMGT +type NnfLustreMGTSpec struct { + // Addresses is the list of LNet addresses for the MGT + Addresses []string `json:"addresses"` + + // FsNameBlackList is a list of fsnames that can't be used. This may be + // necessary if the MGT hosts file systems external to Rabbit + FsNameBlackList []string `json:"fsNameBlackList,omitempty"` + + // FsNameStart is the starting fsname to be used + // +kubebuilder:validation:MaxLength:=8 + // +kubebuilder:validation:MinLength:=8 + FsNameStart string `json:"fsNameStart,omitempty"` + + // FsNameStartReference can be used to add a configmap where the starting fsname is + // stored. If this reference is set, it takes precendence over FsNameStart. The configmap + // will be updated with the next available fsname anytime an fsname is used. + FsNameStartReference corev1.ObjectReference `json:"fsNameStartReference,omitempty"` + + // ClaimList is the list of currently in use fsnames + ClaimList []corev1.ObjectReference `json:"claimList,omitempty"` +} + +// NnfLustreMGTStatus defines the current state of NnfLustreMGT +type NnfLustreMGTStatus struct { + // FsNameNext is the next available fsname that hasn't been used + // +kubebuilder:validation:MaxLength:=8 + // +kubebuilder:validation:MinLength:=8 + FsNameNext string `json:"fsNameNext,omitempty"` + + // ClaimList is the list of currently in use fsnames + ClaimList []NnfLustreMGTStatusClaim `json:"claimList,omitempty"` + + dwsv1alpha2.ResourceError `json:",inline"` +} + +type NnfLustreMGTStatusClaim struct { + Reference corev1.ObjectReference `json:"reference,omitempty"` + FsName string `json:"fsname,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// NnfLustreMGT is the Schema for the nnfstorageprofiles API +type NnfLustreMGT struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec NnfLustreMGTSpec `json:"spec,omitempty"` + Status NnfLustreMGTStatus `json:"status,omitempty"` +} + +func (a *NnfLustreMGT) GetStatus() updater.Status[*NnfLustreMGTStatus] { + return &a.Status +} + +//+kubebuilder:object:root=true + +// NnfLustreMGTList contains a list of NnfLustreMGT +type NnfLustreMGTList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NnfLustreMGT `json:"items"` +} + +func (n *NnfLustreMGTList) GetObjectList() []client.Object { + objectList := []client.Object{} + + for i := range n.Items { + objectList = append(objectList, &n.Items[i]) + } + + return objectList +} + +func init() { + SchemeBuilder.Register(&NnfLustreMGT{}, &NnfLustreMGTList{}) +} diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_node_block_storage_types.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_node_block_storage_types.go index a43cd219..664b93a6 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_node_block_storage_types.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_node_block_storage_types.go @@ -50,6 +50,11 @@ type NnfNodeBlockStorageStatus struct { dwsv1alpha2.ResourceError `json:",inline"` + // PodStartTime is the value of pod.status.containerStatuses[].state.running.startedAt from the pod that did + // last successful full reconcile of the NnfNodeBlockStorage. This is used to tell whether the /dev paths + // listed in the status section are from the current boot of the node. + PodStartTime metav1.Time `json:"podStartTime,omitempty"` + Ready bool `json:"ready"` } diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_storage_types.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_storage_types.go index 1b2ce0cc..63bdb9df 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_storage_types.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnf_storage_types.go @@ -42,10 +42,6 @@ type NnfStorageAllocationNodes struct { // NnfStorageLustreSpec defines the specifications for a Lustre filesystem type NnfStorageLustreSpec struct { - // FileSystemName is the fsname parameter for the Lustre filesystem. - // +kubebuilder:validation:MaxLength:=8 - FileSystemName string `json:"fileSystemName,omitempty"` - // TargetType is the type of Lustre target to be created. // +kubebuilder:validation:Enum=mgt;mdt;mgtmdt;ost TargetType string `json:"targetType,omitempty"` @@ -116,11 +112,23 @@ type NnfStorageAllocationSetStatus struct { AllocationCount int `json:"allocationCount"` } -// NnfStorageStatus defines the observed status of NNF Storage. -type NnfStorageStatus struct { +type NnfStorageLustreStatus struct { // MgsAddress is the NID of the MGS. MgsAddress string `json:"mgsAddress,omitempty"` + // FileSystemName is the fsname parameter for the Lustre filesystem. + // +kubebuilder:validation:MaxLength:=8 + FileSystemName string `json:"fileSystemName,omitempty"` + + // LustgreMgtReference is an object reference to the NnfLustreMGT resource used + // by the NnfStorage + LustreMgtReference corev1.ObjectReference `json:"lustreMgtReference,omitempty"` +} + +// NnfStorageStatus defines the observed status of NNF Storage. +type NnfStorageStatus struct { + NnfStorageLustreStatus `json:",inline"` + // AllocationsSets holds the status information for each of the AllocationSets // from the spec. AllocationSets []NnfStorageAllocationSetStatus `json:"allocationSets,omitempty"` diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go index 29c36ccf..58ab6ccb 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/zz_generated.deepcopy.go @@ -642,6 +642,133 @@ func (in *NnfDriveStatus) DeepCopy() *NnfDriveStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NnfLustreMGT) DeepCopyInto(out *NnfLustreMGT) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfLustreMGT. +func (in *NnfLustreMGT) DeepCopy() *NnfLustreMGT { + if in == nil { + return nil + } + out := new(NnfLustreMGT) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NnfLustreMGT) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NnfLustreMGTList) DeepCopyInto(out *NnfLustreMGTList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NnfLustreMGT, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfLustreMGTList. +func (in *NnfLustreMGTList) DeepCopy() *NnfLustreMGTList { + if in == nil { + return nil + } + out := new(NnfLustreMGTList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NnfLustreMGTList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NnfLustreMGTSpec) DeepCopyInto(out *NnfLustreMGTSpec) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.FsNameBlackList != nil { + in, out := &in.FsNameBlackList, &out.FsNameBlackList + *out = make([]string, len(*in)) + copy(*out, *in) + } + out.FsNameStartReference = in.FsNameStartReference + if in.ClaimList != nil { + in, out := &in.ClaimList, &out.ClaimList + *out = make([]v1.ObjectReference, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfLustreMGTSpec. +func (in *NnfLustreMGTSpec) DeepCopy() *NnfLustreMGTSpec { + if in == nil { + return nil + } + out := new(NnfLustreMGTSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NnfLustreMGTStatus) DeepCopyInto(out *NnfLustreMGTStatus) { + *out = *in + if in.ClaimList != nil { + in, out := &in.ClaimList, &out.ClaimList + *out = make([]NnfLustreMGTStatusClaim, len(*in)) + copy(*out, *in) + } + in.ResourceError.DeepCopyInto(&out.ResourceError) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfLustreMGTStatus. +func (in *NnfLustreMGTStatus) DeepCopy() *NnfLustreMGTStatus { + if in == nil { + return nil + } + out := new(NnfLustreMGTStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NnfLustreMGTStatusClaim) DeepCopyInto(out *NnfLustreMGTStatusClaim) { + *out = *in + out.Reference = in.Reference +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfLustreMGTStatusClaim. +func (in *NnfLustreMGTStatusClaim) DeepCopy() *NnfLustreMGTStatusClaim { + if in == nil { + return nil + } + out := new(NnfLustreMGTStatusClaim) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NnfNode) DeepCopyInto(out *NnfNode) { *out = *in @@ -843,6 +970,7 @@ func (in *NnfNodeBlockStorageStatus) DeepCopyInto(out *NnfNodeBlockStorageStatus } } in.ResourceError.DeepCopyInto(&out.ResourceError) + in.PodStartTime.DeepCopyInto(&out.PodStartTime) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfNodeBlockStorageStatus. @@ -1471,6 +1599,22 @@ func (in *NnfStorageLustreSpec) DeepCopy() *NnfStorageLustreSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NnfStorageLustreStatus) DeepCopyInto(out *NnfStorageLustreStatus) { + *out = *in + out.LustreMgtReference = in.LustreMgtReference +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NnfStorageLustreStatus. +func (in *NnfStorageLustreStatus) DeepCopy() *NnfStorageLustreStatus { + if in == nil { + return nil + } + out := new(NnfStorageLustreStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NnfStorageProfile) DeepCopyInto(out *NnfStorageProfile) { *out = *in @@ -1741,6 +1885,7 @@ func (in *NnfStorageSpec) DeepCopy() *NnfStorageSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NnfStorageStatus) DeepCopyInto(out *NnfStorageStatus) { *out = *in + out.NnfStorageLustreStatus = in.NnfStorageLustreStatus if in.AllocationSets != nil { in, out := &in.AllocationSets, &out.AllocationSets *out = make([]NnfStorageAllocationSetStatus, len(*in)) diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnflustremgts.yaml b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnflustremgts.yaml new file mode 100644 index 00000000..319dcf33 --- /dev/null +++ b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnflustremgts.yaml @@ -0,0 +1,287 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: nnflustremgts.nnf.cray.hpe.com +spec: + group: nnf.cray.hpe.com + names: + kind: NnfLustreMGT + listKind: NnfLustreMGTList + plural: nnflustremgts + singular: nnflustremgt + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NnfLustreMGT is the Schema for the nnfstorageprofiles API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: NnfLustreMGTSpec defines the desired state of NnfLustreMGT + properties: + addresses: + description: Addresses is the list of LNet addresses for the MGT + items: + type: string + type: array + claimList: + description: ClaimList is the list of currently in use fsnames + items: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: array + fsNameBlackList: + description: |- + FsNameBlackList is a list of fsnames that can't be used. This may be + necessary if the MGT hosts file systems external to Rabbit + items: + type: string + type: array + fsNameStart: + description: FsNameStart is the starting fsname to be used + maxLength: 8 + minLength: 8 + type: string + fsNameStartReference: + description: |- + FsNameStartReference can be used to add a configmap where the starting fsname is + stored. If this reference is set, it takes precendence over FsNameStart. The configmap + will be updated with the next available fsname anytime an fsname is used. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + required: + - addresses + type: object + status: + description: NnfLustreMGTStatus defines the current state of NnfLustreMGT + properties: + claimList: + description: ClaimList is the list of currently in use fsnames + items: + properties: + fsname: + type: string + reference: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: object + type: array + error: + description: Error information + properties: + debugMessage: + description: Internal debug message for the error + type: string + severity: + description: |- + Indication of how severe the error is. Minor will likely succeed, Major may + succeed, and Fatal will never succeed. + enum: + - Minor + - Major + - Fatal + type: string + type: + description: Internal or user error + enum: + - Internal + - User + - WLM + type: string + userMessage: + description: Optional user facing message if the error is relevant + to an end user + type: string + required: + - debugMessage + - severity + - type + type: object + fsNameNext: + description: FsNameNext is the next available fsname that hasn't been + used + maxLength: 8 + minLength: 8 + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfnodeblockstorages.yaml b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfnodeblockstorages.yaml index 94431878..836c7486 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfnodeblockstorages.yaml +++ b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfnodeblockstorages.yaml @@ -160,6 +160,13 @@ spec: - severity - type type: object + podStartTime: + description: |- + PodStartTime is the value of pod.status.containerStatuses[].state.running.startedAt from the pod that did + last successful full reconcile of the NnfNodeBlockStorage. This is used to tell whether the /dev paths + listed in the status section are from the current boot of the node. + format: date-time + type: string ready: type: boolean required: diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfstorages.yaml b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfstorages.yaml index 91112a5a..aa976e9f 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfstorages.yaml +++ b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfstorages.yaml @@ -74,11 +74,6 @@ spec: may split the storage among the available drives operating in the NNF Node. format: int64 type: integer - fileSystemName: - description: FileSystemName is the fsname parameter for the - Lustre filesystem. - maxLength: 8 - type: string mgsAddress: description: |- MgsAddress is the NID of the MGS when a pre-existing MGS is @@ -252,6 +247,57 @@ spec: - severity - type type: object + fileSystemName: + description: FileSystemName is the fsname parameter for the Lustre + filesystem. + maxLength: 8 + type: string + lustreMgtReference: + description: |- + LustgreMgtReference is an object reference to the NnfLustreMGT resource used + by the NnfStorage + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic mgsAddress: description: MgsAddress is the NID of the MGS. type: string diff --git a/vendor/modules.txt b/vendor/modules.txt index 291c8434..8f1bf2e0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,7 +10,7 @@ github.com/NearNodeFlash/lustre-fs-operator/config/crd/bases # github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 ## explicit; go 1.19 github.com/NearNodeFlash/nnf-ec/pkg/rfsf/pkg/models -# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240812175705-2729a8a1ebc6 +# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240816013414-a2246392cd0a ## explicit; go 1.21 github.com/NearNodeFlash/nnf-sos/api/v1alpha1 github.com/NearNodeFlash/nnf-sos/config/crd/bases From 5a57d7c7f0085ca62e4b4ad4c6d57d4bf0bed7c4 Mon Sep 17 00:00:00 2001 From: Blake Devcich <89158881+bdevcich@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:58:23 -0500 Subject: [PATCH 10/13] Optional DM mkdir (#197) For things like SCR that are using the Copy Offload API, the destination can easily be created by the client software. SCR guarantees this. Using profiles, allow the destination prep (mkdir to ensure dest exists) to be skipped. This way, copy_in/copy_out can still ensure the dest exists while disabling this behavior for SCR. Signed-off-by: Blake Devcich --- go.mod | 2 +- go.sum | 4 +- .../controller/datamovement_controller.go | 66 ++++++++++--------- .../v1alpha1/nnfdatamovementprofile_types.go | 7 ++ ....cray.hpe.com_nnfdatamovementprofiles.yaml | 9 +++ vendor/modules.txt | 2 +- 6 files changed, 55 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index f2542c88..0e5e7775 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf - github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240816013414-a2246392cd0a + github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141008-b67847b5c8fd github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.32.0 github.com/prometheus/client_golang v1.16.0 diff --git a/go.sum b/go.sum index 12847922..15d8e3ce 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf/go.mod h1:N5X1obpl0mBI0VoCJdQhv7cFXOC6g3VlXj712qWj0JE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 h1:7eT5mOVSNwtacIcGhzMAsi8EVbeS4zk9QwThG2f0GHE= github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5/go.mod h1:oxdwMqfttOF9dabJhqrWlirCnMk8/8eyLMwl+hducjk= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240816013414-a2246392cd0a h1:h08LssHEqjca6mWLHjEPwoozQ01VAslvmUI2aUzTQIM= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240816013414-a2246392cd0a/go.mod h1:uJvjwkSLrPk4A/13U/E4vnO8R+utDE/lGclsKVp/88s= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141008-b67847b5c8fd h1:RxeF/TnVqg8kiLpqAv3HoVnW/DOL5E2szKhXLkQ+d3c= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141008-b67847b5c8fd/go.mod h1:uJvjwkSLrPk4A/13U/E4vnO8R+utDE/lGclsKVp/88s= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/internal/controller/datamovement_controller.go b/internal/controller/datamovement_controller.go index 6396a60e..c4400efc 100644 --- a/internal/controller/datamovement_controller.go +++ b/internal/controller/datamovement_controller.go @@ -270,10 +270,9 @@ func (r *DataMovementReconciler) Reconcile(ctx context.Context, req ctrl.Request log.Info("MPI Hostfile preview", "first line", peekMpiHostfile(mpiHostfile)) // Prepare Destination Directory - if err = r.prepareDestination(ctx, dm, mpiHostfile, log); err != nil { + if err = r.prepareDestination(ctx, profile, mpiHostfile, dm, log); err != nil { return ctrl.Result{}, err } - log.Info("Destination prepared", "dm.Spec.Destination", dm.Spec.Destination) // Build command cmdArgs, err := buildDMCommand(ctx, profile, mpiHostfile, dm) @@ -595,43 +594,48 @@ func buildDMCommand(ctx context.Context, profile *nnfv1alpha1.NnfDataMovementPro return strings.Split(cmd, " "), nil } -func (r *DataMovementReconciler) prepareDestination(ctx context.Context, dm *nnfv1alpha1.NnfDataMovement, mpiHostfile string, log logr.Logger) error { +func (r *DataMovementReconciler) prepareDestination(ctx context.Context, profile *nnfv1alpha1.NnfDataMovementProfile, mpiHostfile string, dm *nnfv1alpha1.NnfDataMovement, log logr.Logger) error { // These functions interact with the filesystem, so they can't run in the test env - if !isTestEnv() { - // Determine the destination directory based on the source and path - log.Info("Determining destination directory based on source/dest file types") - destDir, err := getDestinationDir(dm, mpiHostfile, log) - if err != nil { - return dwsv1alpha2.NewResourceError("could not determine source type").WithError(err).WithFatal() - } + // Also, if the profile disables destination creation, skip it + if isTestEnv() || !profile.Data.CreateDestDir { + return nil + } - // See if an index mount directory on the destination is required - log.Info("Determining if index mount directory is required") - indexMount, err := r.checkIndexMountDir(ctx, dm) - if err != nil { - return dwsv1alpha2.NewResourceError("could not determine index mount directory").WithError(err).WithFatal() - } + // Determine the destination directory based on the source and path + log.Info("Determining destination directory based on source/dest file types") + destDir, err := getDestinationDir(dm, mpiHostfile, log) + if err != nil { + return dwsv1alpha2.NewResourceError("could not determine source type").WithError(err).WithFatal() + } - // Account for index mount directory on the destDir and the dm dest path - // This updates the destination on dm - if indexMount != "" { - log.Info("Index mount directory is required", "indexMountdir", indexMount) - d, err := handleIndexMountDir(destDir, indexMount, dm, mpiHostfile, log) - if err != nil { - return dwsv1alpha2.NewResourceError("could not handle index mount directory").WithError(err).WithFatal() - } - destDir = d - log.Info("Updated destination for index mount directory", "destDir", destDir, "dm.Spec.Destination.Path", dm.Spec.Destination.Path) - } + // See if an index mount directory on the destination is required + log.Info("Determining if index mount directory is required") + indexMount, err := r.checkIndexMountDir(ctx, dm) + if err != nil { + return dwsv1alpha2.NewResourceError("could not determine index mount directory").WithError(err).WithFatal() + } - // Create the destination directory - log.Info("Creating destination directory", "destinationDir", destDir, "indexMountDir", indexMount) - if err := createDestinationDir(destDir, dm.Spec.UserId, dm.Spec.GroupId, mpiHostfile, log); err != nil { - return dwsv1alpha2.NewResourceError("could not create destination directory").WithError(err).WithFatal() + // Account for index mount directory on the destDir and the dm dest path + // This updates the destination on dm + if indexMount != "" { + log.Info("Index mount directory is required", "indexMountdir", indexMount) + d, err := handleIndexMountDir(destDir, indexMount, dm, mpiHostfile, log) + if err != nil { + return dwsv1alpha2.NewResourceError("could not handle index mount directory").WithError(err).WithFatal() } + destDir = d + log.Info("Updated destination for index mount directory", "destDir", destDir, "dm.Spec.Destination.Path", dm.Spec.Destination.Path) } + // Create the destination directory + log.Info("Creating destination directory", "destinationDir", destDir, "indexMountDir", indexMount) + if err := createDestinationDir(destDir, dm.Spec.UserId, dm.Spec.GroupId, mpiHostfile, log); err != nil { + return dwsv1alpha2.NewResourceError("could not create destination directory").WithError(err).WithFatal() + } + + log.Info("Destination prepared", "dm.Spec.Destination", dm.Spec.Destination) return nil + } // Check for a copy_out situation by looking at the source filesystem's type. If it's gfs2 or xfs, diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go index 65b0c59d..5cad69d4 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go +++ b/vendor/github.com/NearNodeFlash/nnf-sos/api/v1alpha1/nnfdatamovementprofile_types.go @@ -75,6 +75,13 @@ type NnfDataMovementProfileData struct { // +kubebuilder:default:=5 // +kubebuilder:validation:Minimum:=0 ProgressIntervalSeconds int `json:"progressIntervalSeconds,omitempty"` + + // CreateDestDir will ensure that the destination directory exists before performing data + // movement. This will cause a number of stat commands to determine the source and destination + // file types, so that the correct pathing for the destination can be determined. Then, a mkdir + // is issued. + // +kubebuilder:default:=true + CreateDestDir bool `json:"createDestDir"` } // +kubebuilder:object:root=true diff --git a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml index 554ca460..28886fe1 100644 --- a/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml +++ b/vendor/github.com/NearNodeFlash/nnf-sos/config/crd/bases/nnf.cray.hpe.com_nnfdatamovementprofiles.yaml @@ -52,6 +52,14 @@ spec: SRC: source for the data movement DEST destination for the data movement type: string + createDestDir: + default: true + description: |- + CreateDestDir will ensure that the destination directory exists before performing data + movement. This will cause a number of stat commands to determine the source and destination + file types, so that the correct pathing for the destination can be determined. Then, a mkdir + is issued. + type: boolean default: default: false description: Default is true if this instance is the default resource @@ -98,6 +106,7 @@ spec: type: boolean required: - command + - createDestDir - maxSlots - slots type: object diff --git a/vendor/modules.txt b/vendor/modules.txt index 8f1bf2e0..19f38cdc 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,7 +10,7 @@ github.com/NearNodeFlash/lustre-fs-operator/config/crd/bases # github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 ## explicit; go 1.19 github.com/NearNodeFlash/nnf-ec/pkg/rfsf/pkg/models -# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240816013414-a2246392cd0a +# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141008-b67847b5c8fd ## explicit; go 1.21 github.com/NearNodeFlash/nnf-sos/api/v1alpha1 github.com/NearNodeFlash/nnf-sos/config/crd/bases From 0867289c1c59b47fe5532da5093e6b29118092c5 Mon Sep 17 00:00:00 2001 From: Anthony Floeder Date: Wed, 21 Aug 2024 11:54:46 -0500 Subject: [PATCH 11/13] update peer modules Signed-off-by: Anthony Floeder --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- .../dws/api/v1alpha2/clientmount_webhook.go | 3 ++- .../dws/api/v1alpha2/computes_webhook.go | 3 ++- .../api/v1alpha2/directivebreakdown_webhook.go | 3 ++- .../dws/api/v1alpha2/dwdirectiverule_webhook.go | 3 ++- .../persistentstorageinstance_webhook.go | 3 ++- .../dws/api/v1alpha2/servers_webhook.go | 3 ++- .../dws/api/v1alpha2/storage_webhook.go | 3 ++- .../api/v1alpha2/systemconfiguration_webhook.go | 3 ++- .../dws/api/v1alpha2/workflow_webhook.go | 8 ++++++-- .../api/v1beta1/lustrefilesystem_webhook.go | 7 +++++-- vendor/modules.txt | 8 ++++---- 13 files changed, 43 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 0e5e7775..6a1eadf8 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/NearNodeFlash/nnf-dm go 1.21 require ( - github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf - github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141008-b67847b5c8fd + github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240820214524-99d5da17471d + github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141947-f61076751e0f github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.32.0 github.com/prometheus/client_golang v1.16.0 @@ -22,7 +22,7 @@ require ( ) require ( - github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 // indirect + github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240820195316-cb407b151cb4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -73,7 +73,7 @@ require ( ) require ( - github.com/DataWorkflowServices/dws v0.0.1-0.20240801173757-1fb2188d84b9 + github.com/DataWorkflowServices/dws v0.0.1-0.20240820212105-5950825b3d74 go.openly.dev/pointy v1.3.0 ) diff --git a/go.sum b/go.sum index 15d8e3ce..81caa0d3 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ -github.com/DataWorkflowServices/dws v0.0.1-0.20240801173757-1fb2188d84b9 h1:Jf5AxKXNxNtDC4YBbnJfpKWr4DicrEJ0aCtIgarIIqU= -github.com/DataWorkflowServices/dws v0.0.1-0.20240801173757-1fb2188d84b9/go.mod h1:6MrEEHISskyooSKcKU6R3mFqH6Yh6KzWgajhcw2s+nM= -github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf h1:ArBI1LR+BBZ9lF+Aohv49RhTpmRqIXLz4L/h45qQT4k= -github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf/go.mod h1:N5X1obpl0mBI0VoCJdQhv7cFXOC6g3VlXj712qWj0JE= -github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 h1:7eT5mOVSNwtacIcGhzMAsi8EVbeS4zk9QwThG2f0GHE= -github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5/go.mod h1:oxdwMqfttOF9dabJhqrWlirCnMk8/8eyLMwl+hducjk= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141008-b67847b5c8fd h1:RxeF/TnVqg8kiLpqAv3HoVnW/DOL5E2szKhXLkQ+d3c= -github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141008-b67847b5c8fd/go.mod h1:uJvjwkSLrPk4A/13U/E4vnO8R+utDE/lGclsKVp/88s= +github.com/DataWorkflowServices/dws v0.0.1-0.20240820212105-5950825b3d74 h1:u0ZqL8mEyKoIOo7ahBTQSjcmdu4O2rzDCO+h9oJ2/O8= +github.com/DataWorkflowServices/dws v0.0.1-0.20240820212105-5950825b3d74/go.mod h1:6MrEEHISskyooSKcKU6R3mFqH6Yh6KzWgajhcw2s+nM= +github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240820214524-99d5da17471d h1:iiE1EhefucdPBJwYfRRGIqDXnBXTV9tfgn+trJc7RSg= +github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240820214524-99d5da17471d/go.mod h1:N5X1obpl0mBI0VoCJdQhv7cFXOC6g3VlXj712qWj0JE= +github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240820195316-cb407b151cb4 h1:cxUkRTnynEvCLbYL+d/FVyITLODO/goscivJLq5kipY= +github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240820195316-cb407b151cb4/go.mod h1:oxdwMqfttOF9dabJhqrWlirCnMk8/8eyLMwl+hducjk= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141947-f61076751e0f h1:TzN+pKBC5jmLri5TEArWCzki4NIkfpxRTyQKev0oRKQ= +github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141947-f61076751e0f/go.mod h1:uTPaHauR9qBPXN9HxWadxK4mrgmuQqBAEboDQI4Okms= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/clientmount_webhook.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/clientmount_webhook.go index 38875b74..c95c432a 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/clientmount_webhook.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/clientmount_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2023 Hewlett Packard Enterprise Development LP + * Copyright 2023-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -27,6 +27,7 @@ import ( // log is for logging in this package. var clientmountlog = logf.Log.WithName("clientmount-resource") +// SetupWebhookWithManager will setup the manager to manage the webhooks func (r *ClientMount) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/computes_webhook.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/computes_webhook.go index 3bbdf423..1d78a40d 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/computes_webhook.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/computes_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2023 Hewlett Packard Enterprise Development LP + * Copyright 2023-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -27,6 +27,7 @@ import ( // log is for logging in this package. var computeslog = logf.Log.WithName("computes-resource") +// SetupWebhookWithManager will setup the manager to manage the webhooks func (r *Computes) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/directivebreakdown_webhook.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/directivebreakdown_webhook.go index ce6b3d99..cc5ac5be 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/directivebreakdown_webhook.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/directivebreakdown_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2023 Hewlett Packard Enterprise Development LP + * Copyright 2023-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -27,6 +27,7 @@ import ( // log is for logging in this package. var directivebreakdownlog = logf.Log.WithName("directivebreakdown-resource") +// SetupWebhookWithManager will setup the manager to manage the webhooks func (r *DirectiveBreakdown) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/dwdirectiverule_webhook.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/dwdirectiverule_webhook.go index 9a3b62eb..82276e70 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/dwdirectiverule_webhook.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/dwdirectiverule_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2023 Hewlett Packard Enterprise Development LP + * Copyright 2023-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -27,6 +27,7 @@ import ( // log is for logging in this package. var dwdirectiverulelog = logf.Log.WithName("dwdirectiverule-resource") +// SetupWebhookWithManager will setup the manager to manage the webhooks func (r *DWDirectiveRule) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/persistentstorageinstance_webhook.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/persistentstorageinstance_webhook.go index b577cdf1..b07b076c 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/persistentstorageinstance_webhook.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/persistentstorageinstance_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2023 Hewlett Packard Enterprise Development LP + * Copyright 2023-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -27,6 +27,7 @@ import ( // log is for logging in this package. var persistentstorageinstancelog = logf.Log.WithName("persistentstorageinstance-resource") +// SetupWebhookWithManager will setup the manager to manage the webhooks func (r *PersistentStorageInstance) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/servers_webhook.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/servers_webhook.go index 179e7faf..2a834f6c 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/servers_webhook.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/servers_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2023 Hewlett Packard Enterprise Development LP + * Copyright 2023-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -27,6 +27,7 @@ import ( // log is for logging in this package. var serverslog = logf.Log.WithName("servers-resource") +// SetupWebhookWithManager will setup the manager to manage the webhooks func (r *Servers) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/storage_webhook.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/storage_webhook.go index aa441246..4c3ae474 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/storage_webhook.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/storage_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2023 Hewlett Packard Enterprise Development LP + * Copyright 2023-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -27,6 +27,7 @@ import ( // log is for logging in this package. var storagelog = logf.Log.WithName("storage-resource") +// SetupWebhookWithManager will setup the manager to manage the webhooks func (r *Storage) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/systemconfiguration_webhook.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/systemconfiguration_webhook.go index 0f3988ea..dab68447 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/systemconfiguration_webhook.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/systemconfiguration_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2023 Hewlett Packard Enterprise Development LP + * Copyright 2023-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -27,6 +27,7 @@ import ( // log is for logging in this package. var systemconfigurationlog = logf.Log.WithName("systemconfiguration-resource") +// SetupWebhookWithManager will setup the manager to manage the webhooks func (r *SystemConfiguration) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/workflow_webhook.go b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/workflow_webhook.go index 6915be80..8b3562db 100644 --- a/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/workflow_webhook.go +++ b/vendor/github.com/DataWorkflowServices/dws/api/v1alpha2/workflow_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -44,7 +44,7 @@ var workflowlog = logf.Log.WithName("workflow-resource") var c client.Client -// SetupWebhookWithManager connects the webhook with the manager +// SetupWebhookWithManager will setup the manager to manage the webhooks func (w *Workflow) SetupWebhookWithManager(mgr ctrl.Manager) error { c = mgr.GetClient() return ctrl.NewWebhookManagedBy(mgr). @@ -52,6 +52,8 @@ func (w *Workflow) SetupWebhookWithManager(mgr ctrl.Manager) error { Complete() } +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + //+kubebuilder:webhook:path=/mutate-dataworkflowservices-github-io-v1alpha2-workflow,mutating=true,failurePolicy=fail,sideEffects=None,groups=dataworkflowservices.github.io,resources=workflows,verbs=create,versions=v1alpha2,name=mworkflow.kb.io,admissionReviewVersions={v1,v1beta1} var _ webhook.Defaulter = &Workflow{} @@ -71,6 +73,8 @@ func (w *Workflow) Default() { } // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +// NOTE: The 'path' attribute must follow a specific pattern and should not be modified directly here. +// Modifying the path for an invalid path can cause API server errors; failing to locate the webhook. //+kubebuilder:webhook:path=/validate-dataworkflowservices-github-io-v1alpha2-workflow,mutating=false,failurePolicy=fail,sideEffects=None,groups=dataworkflowservices.github.io,resources=workflows,verbs=create;update,versions=v1alpha2,name=vworkflow.kb.io,admissionReviewVersions={v1,v1beta1} var _ webhook.Validator = &Workflow{} diff --git a/vendor/github.com/NearNodeFlash/lustre-fs-operator/api/v1beta1/lustrefilesystem_webhook.go b/vendor/github.com/NearNodeFlash/lustre-fs-operator/api/v1beta1/lustrefilesystem_webhook.go index ba0b5605..ccf16477 100644 --- a/vendor/github.com/NearNodeFlash/lustre-fs-operator/api/v1beta1/lustrefilesystem_webhook.go +++ b/vendor/github.com/NearNodeFlash/lustre-fs-operator/api/v1beta1/lustrefilesystem_webhook.go @@ -1,5 +1,5 @@ /* - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2024 Hewlett Packard Enterprise Development LP * Other additional copyright holders may be indicated within. * * The entirety of this work is licensed under the Apache License, @@ -39,15 +39,18 @@ import ( // log is for logging in this package. var lustrefilesystemlog = logf.Log.WithName("lustrefilesystem-resource") +// SetupWebhookWithManager will setup the manager to manage the webhooks func (r *LustreFileSystem) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). Complete() } -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +// NOTE: The 'path' attribute must follow a specific pattern and should not be modified directly here. +// Modifying the path for an invalid path can cause API server errors; failing to locate the webhook. //+kubebuilder:webhook:path=/validate-lus-cray-hpe-com-v1beta1-lustrefilesystem,mutating=false,failurePolicy=fail,sideEffects=None,groups=lus.cray.hpe.com,resources=lustrefilesystems,verbs=create;update,versions=v1beta1,name=vlustrefilesystem.kb.io,admissionReviewVersions=v1 var _ webhook.Validator = &LustreFileSystem{} diff --git a/vendor/modules.txt b/vendor/modules.txt index 19f38cdc..17822d46 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,16 +1,16 @@ -# github.com/DataWorkflowServices/dws v0.0.1-0.20240801173757-1fb2188d84b9 +# github.com/DataWorkflowServices/dws v0.0.1-0.20240820212105-5950825b3d74 ## explicit; go 1.21 github.com/DataWorkflowServices/dws/api/v1alpha2 github.com/DataWorkflowServices/dws/utils/dwdparse github.com/DataWorkflowServices/dws/utils/updater -# github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240709160956-40dcbac0aadf +# github.com/NearNodeFlash/lustre-fs-operator v0.0.1-0.20240820214524-99d5da17471d ## explicit; go 1.21 github.com/NearNodeFlash/lustre-fs-operator/api/v1beta1 github.com/NearNodeFlash/lustre-fs-operator/config/crd/bases -# github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240708183336-34d1295977f5 +# github.com/NearNodeFlash/nnf-ec v0.0.1-0.20240820195316-cb407b151cb4 ## explicit; go 1.19 github.com/NearNodeFlash/nnf-ec/pkg/rfsf/pkg/models -# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141008-b67847b5c8fd +# github.com/NearNodeFlash/nnf-sos v0.0.1-0.20240821141947-f61076751e0f ## explicit; go 1.21 github.com/NearNodeFlash/nnf-sos/api/v1alpha1 github.com/NearNodeFlash/nnf-sos/config/crd/bases From 0c89a41c85abe9c23ddd2269b4f4a07848c6b8ae Mon Sep 17 00:00:00 2001 From: Anthony Floeder Date: Thu, 22 Aug 2024 13:32:58 -0500 Subject: [PATCH 12/13] Update nnf-mfu release references Signed-off-by: Anthony Floeder --- Dockerfile | 2 +- Makefile | 2 +- config/manager/kustomization.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2ed09439..5f086b74 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # These ARGs must be before the first FROM. This allows them to be valid for # use in FROM instructions. ARG NNFMFU_TAG_BASE=ghcr.io/nearnodeflash/nnf-mfu -ARG NNFMFU_VERSION=0.1.0 +ARG NNFMFU_VERSION=0.1.1 # Build the manager binary FROM golang:1.21-alpine AS builder diff --git a/Makefile b/Makefile index 5d85d427..3e6750ce 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ IMAGE_TAG_BASE ?= ghcr.io/nearnodeflash/nnf-dm # The NNF-MFU container image to use in NNFContainerProfile resources. NNFMFU_TAG_BASE ?= ghcr.io/nearnodeflash/nnf-mfu -NNFMFU_VERSION ?= 0.1.0 +NNFMFU_VERSION ?= 0.1.1 CONTAINER_BUILDARGS=--build-arg NNFMFU_TAG_BASE=$(NNFMFU_TAG_BASE) --build-arg NNFMFU_VERSION=$(NNFMFU_VERSION) diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 93c2ea1e..4e785d13 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -19,4 +19,4 @@ images: newTag: 0.1.3 - name: nnf-mfu newName: ghcr.io/nearnodeflash/nnf-mfu - newTag: 0.1.0 + newTag: 0.1.1 From b53b9816317d4474e63f06b5390f8fe5dd7dd9c3 Mon Sep 17 00:00:00 2001 From: Anthony Floeder Date: Thu, 22 Aug 2024 13:32:59 -0500 Subject: [PATCH 13/13] Update own release references Signed-off-by: Anthony Floeder --- config/manager/kustomization.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 4e785d13..d3246e28 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -16,7 +16,7 @@ kind: Kustomization images: - name: controller newName: ghcr.io/nearnodeflash/nnf-dm - newTag: 0.1.3 + newTag: 0.1.4 - name: nnf-mfu newName: ghcr.io/nearnodeflash/nnf-mfu newTag: 0.1.1