From f71bd5d539f6f2a4146a28848e9fe90b9386e2b3 Mon Sep 17 00:00:00 2001 From: Thomas Hipp Date: Wed, 27 Sep 2023 12:50:24 +0200 Subject: [PATCH] patches: Remove invalid block settings from existing volumes Signed-off-by: Thomas Hipp --- lxd/patches.go | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/lxd/patches.go b/lxd/patches.go index 6389f3c74cdb..36a35d28b654 100644 --- a/lxd/patches.go +++ b/lxd/patches.go @@ -77,6 +77,7 @@ var patches = []patch{ {name: "storage_prefix_bucket_names_with_project", stage: patchPostDaemonStorage, run: patchGenericStorage}, {name: "storage_move_custom_iso_block_volumes", stage: patchPostDaemonStorage, run: patchStorageRenameCustomISOBlockVolumes}, {name: "zfs_set_content_type_user_property", stage: patchPostDaemonStorage, run: patchZfsSetContentTypeUserProperty}, + {name: "storage_zfs_unset_invalid_block_settings", stage: patchPostDaemonStorage, run: patchStorageZfsUnsetInvalidBlockSettings}, } type patch struct { @@ -916,4 +917,94 @@ func patchZfsSetContentTypeUserProperty(name string, d *Daemon) error { return nil } +// patchStorageZfsUnsetInvalidBlockSettings removes invalid block settings from volumes. +func patchStorageZfsUnsetInvalidBlockSettings(_ string, d *Daemon) error { + s := d.State() + + // Get all storage pool names. + pools, err := s.DB.Cluster.GetStoragePoolNames() + if err != nil { + // Skip the rest of the patch if no storage pools were found. + if api.StatusErrorCheck(err, http.StatusNotFound) { + return nil + } + + return fmt.Errorf("Failed getting storage pool names: %w", err) + } + + volTypeCustom := db.StoragePoolVolumeTypeCustom + volTypeVM := db.StoragePoolVolumeTypeVM + + poolIDNameMap := make(map[int64]string, 0) + poolVolumes := make(map[int64][]*db.StorageVolume, 0) + + err = s.DB.Cluster.Transaction(s.ShutdownCtx, func(ctx context.Context, tx *db.ClusterTx) error { + for _, pool := range pools { + // Get storage pool ID. + poolID, err := tx.GetStoragePoolID(ctx, pool) + if err != nil { + return fmt.Errorf("Failed getting storage pool ID of pool %q: %w", pool, err) + } + + driverName, err := tx.GetStoragePoolDriver(ctx, poolID) + if err != nil { + return fmt.Errorf("Failed getting storage pool driver of pool %q: %w", pool, err) + } + + if driverName != "zfs" { + continue + } + + // Get the pool's custom storage volumes. + volumes, err := tx.GetStoragePoolVolumes(ctx, poolID, false, db.StorageVolumeFilter{Type: &volTypeCustom}, db.StorageVolumeFilter{Type: &volTypeVM}) + if err != nil { + return fmt.Errorf("Failed getting custom storage volumes of pool %q: %w", pool, err) + } + + if poolVolumes[poolID] == nil { + poolVolumes[poolID] = []*db.StorageVolume{} + } + + poolIDNameMap[poolID] = pool + poolVolumes[poolID] = append(poolVolumes[poolID], volumes...) + } + + return nil + }) + if err != nil { + return err + } + + var volType int + + for pool, volumes := range poolVolumes { + for _, vol := range volumes { + config := vol.Config + + if shared.IsTrue(config["zfs.block_mode"]) { + continue + } + + delete(config, "block.filesystem") + delete(config, "block.mount_options") + + if vol.Type == db.StoragePoolVolumeTypeNameVM { + volType = volTypeVM + } else if vol.Type == db.StoragePoolVolumeTypeNameCustom { + volType = volTypeCustom + } else { + // Should not happen. + continue + } + + err = s.DB.Cluster.UpdateStoragePoolVolume(vol.Project, vol.Name, volType, pool, vol.Description, config) + if err != nil { + return fmt.Errorf("Failed updating volume %q in project %q on pool %q: %w", vol.Name, vol.Project, poolIDNameMap[pool], err) + } + } + } + + return nil +} + // Patches end here