Skip to content

Commit 75d6a1f

Browse files
authored
Instance: Only allow initial.zfs.promote during refresh Update action (#18071)
Only allow `initial.zfs.promote` to be specified during `lxc copy` operations. Don't allow `lxc config device set c1 root initial.zfs.promote=true` as this does not make sense for the purpose of `zfs.promote`.
2 parents be66f47 + 4653ecb commit 75d6a1f

14 files changed

Lines changed: 51 additions & 25 deletions

lxd/api_cluster_member.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1970,7 +1970,7 @@ func restoreClusterMember(d *Daemon, r *http.Request, mode string) response.Resp
19701970
ExpiryDate: inst.ExpiryDate(),
19711971
}
19721972

1973-
err = inst.Update(args, false)
1973+
err = inst.Update(args, instance.UpdateActionInternal)
19741974
if err != nil {
19751975
return fmt.Errorf("Failed updating instance %q: %w", inst.Name(), err)
19761976
}

lxd/instance.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func instanceCreateAsCopy(s *state.State, opts instanceCreateAsCopyOpts, op *ope
271271
opts.refresh = false // Instance doesn't exist, so switch to copy mode.
272272
} else {
273273
// Validate and apply refresh target config before the storage refresh.
274-
err = inst.Update(opts.targetInstance, true)
274+
err = inst.Update(opts.targetInstance, instance.UpdateActionUserRefresh)
275275
if err != nil {
276276
return nil, fmt.Errorf("Failed applying refresh target instance config: %w", err)
277277
}

lxd/instance/drivers/driver_common.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -590,15 +590,15 @@ func (d *common) restartCommon(inst instance.Instance, timeout time.Duration) er
590590
Snapshot: inst.IsSnapshot(),
591591
}
592592

593-
err := inst.Update(args, false)
593+
err := inst.Update(args, instance.UpdateActionInternal)
594594
if err != nil {
595595
return err
596596
}
597597

598598
// On function return, set the flag back on
599599
defer func() {
600600
args.Ephemeral = ephemeral
601-
_ = inst.Update(args, false)
601+
_ = inst.Update(args, instance.UpdateActionInternal)
602602
}()
603603
}
604604

@@ -1188,7 +1188,7 @@ func (d *common) restoreCommon(inst instance.Instance, source instance.Instance,
11881188
Snapshot: d.IsSnapshot(),
11891189
}
11901190

1191-
err := inst.Update(args, false)
1191+
err := inst.Update(args, instance.UpdateActionInternal)
11921192
if err != nil {
11931193
op.Done(err)
11941194
return false, nil, err
@@ -1197,7 +1197,7 @@ func (d *common) restoreCommon(inst instance.Instance, source instance.Instance,
11971197
// On function return, set the flag back on.
11981198
defer func() {
11991199
args.Ephemeral = ephemeral
1200-
err = inst.Update(args, false)
1200+
err = inst.Update(args, instance.UpdateActionInternal)
12011201
if err != nil {
12021202
d.logger.Error("Failed restoring ephemeral flag after restore", logger.Ctx{"err": err})
12031203
}
@@ -1236,7 +1236,7 @@ func (d *common) restoreCommon(inst instance.Instance, source instance.Instance,
12361236

12371237
// Don't pass as user-requested as there's no way to fix a bad config.
12381238
// This will call d.UpdateBackupFile() to ensure snapshot list is up to date.
1239-
err = inst.Update(args, false)
1239+
err = inst.Update(args, instance.UpdateActionInternal)
12401240
if err != nil {
12411241
op.Done(err)
12421242
return false, nil, err
@@ -1400,6 +1400,11 @@ func (d *common) isStartableStatusCode(statusCode api.StatusCode) error {
14001400
return nil
14011401
}
14021402

1403+
// isUserRequested returns whether the update action is user-requested.
1404+
func (d *common) isUserRequested(actionType instance.UpdateAction) bool {
1405+
return actionType == instance.UpdateActionUser || actionType == instance.UpdateActionUserRefresh
1406+
}
1407+
14031408
// getStartupSnapNameAndExpiry returns the name and expiry for a snapshot to be taken at startup.
14041409
func (d *common) getStartupSnapNameAndExpiry(inst instance.Instance) (string, *time.Time, error) {
14051410
schedule := strings.ToLower(d.expandedConfig["snapshots.schedule"])
@@ -2235,7 +2240,7 @@ func (d *common) removeDiskDevices() error {
22352240
}
22362241

22372242
// validateConfig validates the configuration.
2238-
func (d *common) validateConfig(allUpdatedDeviceKeys []string, addDevices deviceConfig.Devices, removeDevices deviceConfig.Devices, oldExpandedDevices deviceConfig.Devices, changedConfigKeys []string, oldExpandedConfig map[string]string, userRequested bool) error {
2243+
func (d *common) validateConfig(allUpdatedDeviceKeys []string, addDevices deviceConfig.Devices, removeDevices deviceConfig.Devices, oldExpandedDevices deviceConfig.Devices, changedConfigKeys []string, oldExpandedConfig map[string]string, actionType instance.UpdateAction) error {
22392244
if shared.StringPrefixInSlice(deviceConfig.ConfigInitialPrefix, allUpdatedDeviceKeys) {
22402245
for devName, newDev := range addDevices {
22412246
for k, newVal := range newDev {
@@ -2248,8 +2253,8 @@ func (d *common) validateConfig(allUpdatedDeviceKeys []string, addDevices device
22482253
return fmt.Errorf("New device %q with initial configuration %q cannot be added once the instance is created", devName, k)
22492254
}
22502255

2251-
if k == deviceConfig.ConfigInitialPrefix+"zfs.promote" {
2252-
// Allow zfs.promote to be added as this is needed for volume promotion.
2256+
if actionType == instance.UpdateActionUserRefresh && k == deviceConfig.ConfigInitialPrefix+"zfs.promote" {
2257+
// Allow zfs.promote to be added only during refresh as this is needed for volume promotion.
22532258
continue
22542259
}
22552260

@@ -2266,6 +2271,8 @@ func (d *common) validateConfig(allUpdatedDeviceKeys []string, addDevices device
22662271
}
22672272
}
22682273

2274+
userRequested := d.isUserRequested(actionType)
2275+
22692276
if userRequested {
22702277
// Look for deleted protected keys.
22712278
protectedKeys := map[string]struct{}{

lxd/instance/drivers/driver_lxc.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3742,10 +3742,12 @@ func (d *lxc) CGroupSet(key string, value string) error {
37423742
}
37433743

37443744
// Update applies updated config.
3745-
func (d *lxc) Update(args db.InstanceArgs, userRequested bool) error {
3745+
func (d *lxc) Update(args db.InstanceArgs, actionType instance.UpdateAction) error {
37463746
reverter := revert.New()
37473747
defer reverter.Fail()
37483748

3749+
userRequested := d.isUserRequested(actionType)
3750+
37493751
unlock, err := d.updateBackupFileLock(context.Background())
37503752
if err != nil {
37513753
return err
@@ -3949,7 +3951,7 @@ func (d *lxc) Update(args db.InstanceArgs, userRequested bool) error {
39493951
return newDevType.UpdatableFields(oldDevType)
39503952
})
39513953

3952-
err = d.validateConfig(allUpdatedDeviceKeys, addDevices, removeDevices, oldExpandedDevices, changedConfig, oldExpandedConfig, userRequested)
3954+
err = d.validateConfig(allUpdatedDeviceKeys, addDevices, removeDevices, oldExpandedDevices, changedConfig, oldExpandedConfig, actionType)
39533955
if err != nil {
39543956
return err
39553957
}

lxd/instance/drivers/driver_qemu.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5759,7 +5759,9 @@ func allowRemoveSecurityProtectionStart(state *state.State, poolName string, vol
57595759
}
57605760

57615761
// Update the instance config.
5762-
func (d *qemu) Update(args db.InstanceArgs, userRequested bool) error {
5762+
func (d *qemu) Update(args db.InstanceArgs, actionType instance.UpdateAction) error {
5763+
userRequested := d.isUserRequested(actionType)
5764+
57635765
unlock, err := d.updateBackupFileLock(context.Background())
57645766
if err != nil {
57655767
return err
@@ -5958,7 +5960,7 @@ func (d *qemu) Update(args db.InstanceArgs, userRequested bool) error {
59585960
return newDevType.UpdatableFields(oldDevType)
59595961
})
59605962

5961-
err = d.validateConfig(allUpdatedDeviceKeys, addDevices, removeDevices, oldExpandedDevices, changedConfig, oldExpandedConfig, userRequested)
5963+
err = d.validateConfig(allUpdatedDeviceKeys, addDevices, removeDevices, oldExpandedDevices, changedConfig, oldExpandedConfig, actionType)
59625964
if err != nil {
59635965
return err
59645966
}

lxd/instance/instance_interface.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ const (
4646
// TemplateTrigger trigger name.
4747
type TemplateTrigger string
4848

49+
// UpdateAction defines the trigger source for an instance update.
50+
type UpdateAction int
51+
52+
const (
53+
// UpdateActionUser indicates an update directly requested by users.
54+
UpdateActionUser UpdateAction = iota
55+
56+
// UpdateActionUserRefresh indicates an update requested by user requested refresh workflows.
57+
UpdateActionUserRefresh
58+
59+
// UpdateActionInternal indicates an internal update not directly user requested.
60+
UpdateActionInternal
61+
)
62+
4963
// TemplateTriggerCreate for when an instance is created.
5064
const TemplateTriggerCreate TemplateTrigger = "create"
5165

@@ -100,7 +114,7 @@ type Instance interface {
100114

101115
// Config handling.
102116
Rename(newName string, applyTemplateTrigger bool) error
103-
Update(newConfig db.InstanceArgs, userRequested bool) error
117+
Update(newConfig db.InstanceArgs, actionType UpdateAction) error
104118

105119
Delete(force bool, diskVolumesMode string) error
106120
Export(w io.Writer, properties map[string]string, expiration time.Time, tracker *ioprogress.ProgressTracker) (api.ImageMetadata, error)

lxd/instance_patch.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ func instancePatch(d *Daemon, r *http.Request) response.Response {
236236
Project: projectName,
237237
}
238238

239-
err = c.Update(args, true)
239+
err = c.Update(args, instance.UpdateActionUser)
240240
if err != nil {
241241
return response.SmartError(err)
242242
}

lxd/instance_put.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func instancePut(d *Daemon, r *http.Request) response.Response {
177177
Project: projectName,
178178
}
179179

180-
err = inst.Update(args, true)
180+
err = inst.Update(args, instance.UpdateActionUser)
181181
if err != nil {
182182
return err
183183
}

lxd/instance_snapshot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ func snapshotPut(s *state.State, r *http.Request, snapInst instance.Instance) re
538538
Snapshot: snapInst.IsSnapshot(),
539539
}
540540

541-
err = snapInst.Update(args, false)
541+
err = snapInst.Update(args, instance.UpdateActionInternal)
542542
if err != nil {
543543
return err
544544
}

lxd/instance_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ func (suite *containerTestSuite) TestContainer_AddRoutedNicValidation() {
296296
"eth1": eth1,
297297
},
298298
Name: "testFoo",
299-
}, true)
299+
}, instance.UpdateActionUser)
300300
suite.Req.NoError(err, "Adding multiple routed with gateway mode ['none'] should succeed.")
301301

302302
eth0["ipv6.gateway"] = "auto"
@@ -310,7 +310,7 @@ func (suite *containerTestSuite) TestContainer_AddRoutedNicValidation() {
310310
"eth1": eth1,
311311
},
312312
Name: "testFoo",
313-
}, true)
313+
}, instance.UpdateActionUser)
314314
suite.Req.Error(err,
315315
"Adding multiple routed nic devices with any gateway mode ['auto',''] should throw error.")
316316

@@ -323,7 +323,7 @@ func (suite *containerTestSuite) TestContainer_AddRoutedNicValidation() {
323323
"eth2": eth2,
324324
},
325325
Name: "testFoo",
326-
}, true)
326+
}, instance.UpdateActionUser)
327327
suite.Req.NoError(err,
328328
"Adding multiple nic devices with unique nictype ['routed'] should throw error.")
329329
}

0 commit comments

Comments
 (0)