@@ -24,6 +24,7 @@ import (
2424 "context"
2525 "crypto/sha256"
2626 "encoding/binary"
27+ "slices"
2728 "sort"
2829 "strconv"
2930 "strings"
@@ -82,18 +83,21 @@ func New(dialer Dialer) *Dispatcher {
8283}
8384
8485// Apply builds the DesiredResource for this Resource (looking up its
85- // peers from the full RD-wide list) and sends it to the target
86- // satellite. Returns the per-resource result the satellite reported.
86+ // peers from the full RD-wide list and its volumes from the parent
87+ // RD) and sends it to the target satellite. Returns the per-resource
88+ // result the satellite reported.
8789//
8890// nodes is the full Node CRD list — Apply uses it to resolve each
89- // peer's SatelliteEndpoint property.
90- func (d * Dispatcher ) Apply (ctx context.Context , target * blockstoriov1alpha1.Resource , peers []blockstoriov1alpha1.Resource , nodes []blockstoriov1alpha1.Node ) (* satellitepb.ResourceApplyResult , error ) {
91+ // peer's SatelliteEndpoint property. rd may be nil; when present the
92+ // RD's VolumeDefinitions become DesiredVolumes for non-DISKLESS
93+ // replicas (DISKLESS replicas ignore them).
94+ func (d * Dispatcher ) Apply (ctx context.Context , target * blockstoriov1alpha1.Resource , peers []blockstoriov1alpha1.Resource , nodes []blockstoriov1alpha1.Node , rd * blockstoriov1alpha1.ResourceDefinition ) (* satellitepb.ResourceApplyResult , error ) {
9195 endpoint := lookupEndpoint (target .Spec .NodeName , nodes )
9296 if endpoint == "" {
9397 return nil , errors .Errorf ("no SatelliteEndpoint for node %q" , target .Spec .NodeName )
9498 }
9599
96- desired := buildDesired (target , peers , nodes )
100+ desired := buildDesired (target , peers , nodes , rd )
97101
98102 client , closer , err := d .dialer .Dial (ctx , endpoint )
99103 if err != nil {
@@ -135,7 +139,7 @@ func lookupEndpoint(nodeName string, nodes []blockstoriov1alpha1.Node) string {
135139// nodes is consulted for each peer's `SatelliteEndpoint` prop so
136140// `peer.<name>.address` carries a real (pod) IP rather than a 0.0.0.0
137141// placeholder; drbd-9 won't replicate to 0.0.0.0.
138- func buildDesired (target * blockstoriov1alpha1.Resource , peers []blockstoriov1alpha1.Resource , nodes []blockstoriov1alpha1.Node ) * satellitepb.DesiredResource {
142+ func buildDesired (target * blockstoriov1alpha1.Resource , peers []blockstoriov1alpha1.Resource , nodes []blockstoriov1alpha1.Node , rd * blockstoriov1alpha1. ResourceDefinition ) * satellitepb.DesiredResource {
139143 rdName := target .Spec .ResourceDefinitionName
140144 port := derivePort (rdName )
141145 minor := deriveMinor (rdName )
@@ -189,10 +193,43 @@ func buildDesired(target *blockstoriov1alpha1.Resource, peers []blockstoriov1alp
189193 Flags : target .Spec .Flags ,
190194 Props : target .Spec .Props ,
191195 Peers : dropped ,
196+ Volumes : buildVolumes (rd , target ),
192197 DrbdOptions : drbdOpts ,
193198 }
194199}
195200
201+ // buildVolumes turns the parent ResourceDefinition's VolumeDefinitions
202+ // into DesiredVolumes for the satellite. DISKLESS replicas get an
203+ // empty list — they don't allocate local storage. The StoragePool name
204+ // comes from the Resource's `StorPoolName` prop (LINSTOR-compatible
205+ // key) with the RD-level fallback.
206+ func buildVolumes (rd * blockstoriov1alpha1.ResourceDefinition , target * blockstoriov1alpha1.Resource ) []* satellitepb.DesiredVolume {
207+ if rd == nil {
208+ return nil
209+ }
210+
211+ if slices .Contains (target .Spec .Flags , "DISKLESS" ) {
212+ return nil
213+ }
214+
215+ pool := target .Spec .Props ["StorPoolName" ]
216+ if pool == "" {
217+ pool = rd .Spec .Props ["StorPoolName" ]
218+ }
219+
220+ out := make ([]* satellitepb.DesiredVolume , 0 , len (rd .Spec .VolumeDefinitions ))
221+
222+ for _ , vd := range rd .Spec .VolumeDefinitions {
223+ out = append (out , & satellitepb.DesiredVolume {
224+ VolumeNumber : vd .VolumeNumber ,
225+ SizeKib : vd .SizeKib ,
226+ StoragePool : pool ,
227+ })
228+ }
229+
230+ return out
231+ }
232+
196233// peerAddress looks up `nodeName`'s SatelliteEndpoint and returns
197234// just the host part (no port). Falls back to the 0.0.0.0 placeholder
198235// when the node is unknown or hasn't registered yet — the satellite
0 commit comments