Skip to content

Commit

Permalink
backport of commit 9b74e11
Browse files Browse the repository at this point in the history
  • Loading branch information
gulducat authored Sep 26, 2023
1 parent 3c53d8f commit 2ed1988
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 37 deletions.
10 changes: 1 addition & 9 deletions nomad/state/state_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -2428,18 +2428,10 @@ func (s *StateStore) UpsertCSIVolume(index uint64, volumes []*structs.CSIVolume)
old.Provider != v.Provider {
return fmt.Errorf("volume identity cannot be updated: %s", v.ID)
}

// Update fields that are safe to change while volume is being used.
if err := old.UpdateSafeFields(v); err != nil {
return fmt.Errorf("unable to update in-use volume: %w", err)
}
v = old
v.ModifyIndex = index

} else {
v.CreateIndex = index
v.ModifyIndex = index
}
v.ModifyIndex = index

// Allocations are copy on write, so we want to keep the Allocation ID
// but we need to clear the pointer so that we don't store it when we
Expand Down
26 changes: 9 additions & 17 deletions nomad/structs/csi.go
Original file line number Diff line number Diff line change
Expand Up @@ -813,9 +813,15 @@ func (v *CSIVolume) Merge(other *CSIVolume) error {
}
}

// MountOptions can be updated so long as the volume isn't in use,
// but the caller will reject updating an in-use volume
v.MountOptions = other.MountOptions
// MountOptions can be updated so long as the volume isn't in use
if v.InUse() {
if !v.MountOptions.Equal(other.MountOptions) {
errs = multierror.Append(errs, errors.New(
"can not update mount options while volume is in use"))
}
} else {
v.MountOptions = other.MountOptions
}

// Secrets can be updated freely
v.Secrets = other.Secrets
Expand All @@ -833,20 +839,6 @@ func (v *CSIVolume) Merge(other *CSIVolume) error {
return errs.ErrorOrNil()
}

// UpdateSafeFields updates fields that may be mutated while the volume is in use.
func (v *CSIVolume) UpdateSafeFields(other *CSIVolume) error {
if v == nil || other == nil {
return errors.New("unexpected nil volume (this is a bug)")
}

// Expand operation can sometimes happen while in-use.
v.Capacity = other.Capacity
v.RequestedCapacityMin = other.RequestedCapacityMin
v.RequestedCapacityMax = other.RequestedCapacityMax

return nil
}

// Request and response wrappers
type CSIVolumeRegisterRequest struct {
Volumes []*CSIVolume
Expand Down
43 changes: 32 additions & 11 deletions nomad/structs/csi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/hashicorp/nomad/ci"
"github.com/shoenig/test"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -626,7 +627,7 @@ func TestCSIVolume_Merge(t *testing.T) {
update: &CSIVolume{},
expected: "volume topology request update was not compatible with existing topology",
expectFn: func(t *testing.T, v *CSIVolume) {
require.Len(t, v.Topologies, 1)
must.Len(t, 1, v.Topologies)
},
},
{
Expand All @@ -646,8 +647,8 @@ func TestCSIVolume_Merge(t *testing.T) {
},
expected: "volume topology request update was not compatible with existing topology",
expectFn: func(t *testing.T, v *CSIVolume) {
require.Len(t, v.Topologies, 1)
require.Equal(t, "R1", v.Topologies[0].Segments["rack"])
must.Len(t, 1, v.Topologies)
must.Eq(t, "R1", v.Topologies[0].Segments["rack"])
},
},
{
Expand Down Expand Up @@ -675,6 +676,20 @@ func TestCSIVolume_Merge(t *testing.T) {
},
expected: "volume topology request update was not compatible with existing topology",
},
{
name: "invalid mount options while in use",
v: &CSIVolume{
// having any allocs means it's "in use"
ReadAllocs: map[string]*Allocation{
"test-alloc": {ID: "anything"},
},
},
update: &CSIVolume{
MountOptions: &CSIMountOptions{
MountFlags: []string{"any flags"}},
},
expected: "can not update mount options while volume is in use",
},
{
name: "valid update",
v: &CSIVolume{
Expand Down Expand Up @@ -704,7 +719,7 @@ func TestCSIVolume_Merge(t *testing.T) {
},
MountOptions: &CSIMountOptions{
FSType: "ext4",
MountFlags: []string{"noatime"},
MountFlags: []string{"noatime", "another"},
},
RequestedTopologies: &CSITopologyRequest{
Required: []*CSITopology{
Expand All @@ -725,20 +740,26 @@ func TestCSIVolume_Merge(t *testing.T) {
},
},
},
expectFn: func(t *testing.T, v *CSIVolume) {
test.Len(t, 2, v.RequestedCapabilities,
test.Sprint("should add 2 requested capabilities"))
test.Eq(t, []string{"noatime", "another"}, v.MountOptions.MountFlags,
test.Sprint("should add mount flag"))
},
},
}
for _, tc := range testCases {
tc = tc
tc := tc
t.Run(tc.name, func(t *testing.T) {
err := tc.v.Merge(tc.update)
if tc.expectFn != nil {
tc.expectFn(t, tc.v)
}
if tc.expected == "" {
require.NoError(t, err)
must.NoError(t, err)
} else {
if tc.expectFn != nil {
tc.expectFn(t, tc.v)
}
require.Error(t, err, tc.expected)
require.Contains(t, err.Error(), tc.expected)
must.Error(t, err)
must.ErrorContains(t, err, tc.expected)
}
})
}
Expand Down

0 comments on commit 2ed1988

Please sign in to comment.