Skip to content

Commit be1e70e

Browse files
authored
Merge pull request #1946 from stgraber/main
Fix refresh migrations in cluster and speed up ZFS startup
2 parents 0339643 + 45b9c1d commit be1e70e

File tree

2 files changed

+107
-19
lines changed

2 files changed

+107
-19
lines changed

cmd/incusd/instances_post.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,31 @@ func instancesPost(d *Daemon, r *http.Request) response.Response {
938938
}
939939
}
940940

941+
// Special handling for instance refresh.
942+
// For all other situations, we're headed towards the scheduler, but for this case, we can short circuit it.
943+
if s.ServerClustered && !clusterNotification && req.Source.Type == "migration" && req.Source.Refresh {
944+
client, err := cluster.ConnectIfInstanceIsRemote(s, targetProjectName, req.Name, r, instancetype.Any)
945+
if err != nil && !response.IsNotFoundError(err) {
946+
return response.SmartError(err)
947+
}
948+
949+
if client != nil {
950+
// The request needs to be forwarded to the correct server.
951+
op, err := client.CreateInstance(req)
952+
if err != nil {
953+
return response.SmartError(err)
954+
}
955+
956+
opAPI := op.Get()
957+
return operations.ForwardedOperationResponse(targetProjectName, &opAPI)
958+
}
959+
960+
if err == nil {
961+
// The instance is valid and the request wasn't forwarded, so the instance is local.
962+
return createFromMigration(r.Context(), s, r, targetProjectName, nil, &req)
963+
}
964+
}
965+
941966
var targetProject *api.Project
942967
var profiles []api.Profile
943968
var sourceInst *dbCluster.Instance

internal/server/storage/drivers/driver_zfs.go

Lines changed: 82 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -162,43 +162,106 @@ func (d *zfs) Info() Info {
162162
// Accepts warnOnExistingPolicyApplyError argument, if true will warn rather than fail if applying current policy
163163
// to an existing dataset fails.
164164
func (d zfs) ensureInitialDatasets(warnOnExistingPolicyApplyError bool) error {
165-
args := make([]string, 0, len(zfsDefaultSettings))
165+
// Build the list of datasets to query.
166+
datasets := []string{d.config["zfs.pool_name"]}
167+
for _, entry := range d.initialDatasets() {
168+
datasets = append(datasets, filepath.Join(d.config["zfs.pool_name"], entry))
169+
}
170+
171+
// Build the list of properties to check.
172+
props := []string{"name", "mountpoint", "volmode"}
173+
for k := range zfsDefaultSettings {
174+
props = append(props, k)
175+
}
176+
177+
// Get current state.
178+
args := append([]string{"get", "-H", "-p", "-o", "name,property,value", strings.Join(props, ",")}, datasets...)
179+
output, _ := subprocess.RunCommand("zfs", args...)
180+
181+
currentConfig := map[string]map[string]string{}
182+
for _, entry := range strings.Split(output, "\n") {
183+
if entry == "" {
184+
continue
185+
}
186+
187+
fields := strings.Fields(entry)
188+
if len(fields) != 3 {
189+
continue
190+
}
191+
192+
if currentConfig[fields[0]] == nil {
193+
currentConfig[fields[0]] = map[string]string{}
194+
}
195+
196+
currentConfig[fields[0]][fields[1]] = fields[2]
197+
}
198+
199+
// Check that the root dataset is correctly configured.
200+
args = []string{}
166201
for k, v := range zfsDefaultSettings {
202+
current := currentConfig[d.config["zfs.pool_name"]][k]
203+
if current == v {
204+
continue
205+
}
206+
207+
// Workaround for values having been renamed over time.
208+
if k == "acltype" && current == "posix" {
209+
continue
210+
}
211+
212+
if k == "xattr" && current == "on" {
213+
continue
214+
}
215+
167216
args = append(args, fmt.Sprintf("%s=%s", k, v))
168217
}
169218

170-
err := d.setDatasetProperties(d.config["zfs.pool_name"], args...)
171-
if err != nil {
172-
if warnOnExistingPolicyApplyError {
219+
if len(args) > 0 {
220+
err := d.setDatasetProperties(d.config["zfs.pool_name"], args...)
221+
if err != nil {
222+
if !warnOnExistingPolicyApplyError {
223+
return fmt.Errorf("Failed applying policy to existing dataset %q: %w", d.config["zfs.pool_name"], err)
224+
}
225+
173226
d.logger.Warn("Failed applying policy to existing dataset", logger.Ctx{"dataset": d.config["zfs.pool_name"], "err": err})
174-
} else {
175-
return fmt.Errorf("Failed applying policy to existing dataset %q: %w", d.config["zfs.pool_name"], err)
176227
}
177228
}
178229

230+
// Check the initial datasets.
179231
for _, dataset := range d.initialDatasets() {
180-
properties := []string{"mountpoint=legacy"}
232+
properties := map[string]string{"mountpoint": "legacy"}
181233
if slices.Contains([]string{"virtual-machines", "deleted/virtual-machines"}, dataset) {
182-
properties = append(properties, "volmode=none")
234+
properties["volmode"] = "none"
183235
}
184236

185237
datasetPath := filepath.Join(d.config["zfs.pool_name"], dataset)
186-
exists, err := d.datasetExists(datasetPath)
187-
if err != nil {
188-
return err
189-
}
238+
if currentConfig[datasetPath] != nil {
239+
args := []string{}
240+
for k, v := range properties {
241+
if currentConfig[datasetPath][k] == v {
242+
continue
243+
}
244+
245+
args = append(args, fmt.Sprintf("%s=%s", k, v))
246+
}
247+
248+
if len(args) > 0 {
249+
err := d.setDatasetProperties(datasetPath, args...)
250+
if err != nil {
251+
if !warnOnExistingPolicyApplyError {
252+
return fmt.Errorf("Failed applying policy to existing dataset %q: %w", datasetPath, err)
253+
}
190254

191-
if exists {
192-
err = d.setDatasetProperties(datasetPath, properties...)
193-
if err != nil {
194-
if warnOnExistingPolicyApplyError {
195255
d.logger.Warn("Failed applying policy to existing dataset", logger.Ctx{"dataset": datasetPath, "err": err})
196-
} else {
197-
return fmt.Errorf("Failed applying policy to existing dataset %q: %w", datasetPath, err)
198256
}
199257
}
200258
} else {
201-
err = d.createDataset(datasetPath, properties...)
259+
args := []string{}
260+
for k, v := range properties {
261+
args = append(args, fmt.Sprintf("%s=%s", k, v))
262+
}
263+
264+
err := d.createDataset(datasetPath, args...)
202265
if err != nil {
203266
return fmt.Errorf("Failed creating dataset %q: %w", datasetPath, err)
204267
}

0 commit comments

Comments
 (0)