From 9a5914048c66ebcaef1614f9efc0c656d8dff63a Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Fri, 14 Feb 2025 20:00:10 +0400 Subject: [PATCH] refactor: ephemeral mount Mount EPHEMERAL volume via new controller. Implement the first cut of volume dependencies from services, refactor the way system disk wipe works. Update volume manager controller to destroy volume statuses on shutdown, which allows to signal mount operations to be terminated. Lots of WIP ideas still, but I want to complete this PR and move on to the next one: * refactor user disks mounts to use new API * refactor STATE mountes to use new API * implement directory/overlay mounts Signed-off-by: Andrey Smirnov --- api/resource/definitions/block/block.proto | 6 +- go.mod | 6 +- go.sum | 11 +- .../server/v1alpha1/v1alpha1_server.go | 15 +- .../block/internal/volumes/encrypt.go | 17 + .../block/internal/volumes/volumes.go | 2 +- .../machined/pkg/controllers/block/mount.go | 10 +- .../pkg/controllers/block/volume_config.go | 5 +- .../pkg/controllers/block/volume_manager.go | 140 ++--- .../pkg/controllers/runtime/mount_status.go | 104 ++++ .../app/machined/pkg/runtime/sequencer.go | 1 + .../v1alpha1/v1alpha1_sequencer_tasks.go | 106 ++-- .../runtime/v1alpha2/v1alpha2_controller.go | 1 + .../machined/pkg/system/integration_test.go | 4 + .../app/machined/pkg/system/mocks_test.go | 4 + internal/app/machined/pkg/system/service.go | 2 + .../app/machined/pkg/system/service_runner.go | 35 +- .../app/machined/pkg/system/services/apid.go | 5 + .../machined/pkg/system/services/auditd.go | 5 + .../pkg/system/services/containerd.go | 5 + .../app/machined/pkg/system/services/cri.go | 5 + .../machined/pkg/system/services/dashboard.go | 5 + .../app/machined/pkg/system/services/etcd.go | 5 + .../machined/pkg/system/services/extension.go | 5 + .../machined/pkg/system/services/kubelet.go | 5 + .../machined/pkg/system/services/machined.go | 5 + .../machined/pkg/system/services/registryd.go | 1 + .../machined/pkg/system/services/syslogd.go | 5 + .../machined/pkg/system/services/trustd.go | 5 + .../app/machined/pkg/system/services/udevd.go | 5 + internal/app/machined/pkg/system/volumes.go | 94 ++++ internal/pkg/meta/meta.go | 5 + pkg/conditions/all.go | 7 + .../resource/definitions/block/block.pb.go | 477 ++++++++++-------- .../definitions/block/block_vtproto.pb.go | 182 +++++-- pkg/machinery/go.mod | 6 +- pkg/machinery/go.sum | 12 +- pkg/machinery/resources/block/block.go | 39 ++ .../resources/block/deep_copy.generated.go | 10 +- .../resources/block/mount_request.go | 26 +- pkg/machinery/resources/block/mount_status.go | 16 +- .../resources/block/volume_config.go | 4 +- .../resources/block/volume_mount_request.go | 6 +- .../resources/block/volume_mount_status.go | 6 +- .../resources/block/volume_status.go | 15 +- website/content/v1.10/reference/api.md | 6 +- 46 files changed, 1021 insertions(+), 420 deletions(-) create mode 100644 internal/app/machined/pkg/controllers/runtime/mount_status.go create mode 100644 internal/app/machined/pkg/system/volumes.go diff --git a/api/resource/definitions/block/block.proto b/api/resource/definitions/block/block.proto index 4f1f317a3..ab36ce149 100755 --- a/api/resource/definitions/block/block.proto +++ b/api/resource/definitions/block/block.proto @@ -124,7 +124,7 @@ message MountRequestSpec { message MountSpec { string target_path = 1; string selinux_label = 2; - repeated string options = 3; + bool project_quota_support = 3; } // MountStatusSpec is the spec for MountStatus. @@ -134,6 +134,8 @@ message MountStatusSpec { string source = 3; talos.resource.definitions.enums.BlockFilesystemType filesystem = 4; bool read_only = 5; + bool project_quota_support = 6; + talos.resource.definitions.enums.BlockEncryptionProviderType encryption_provider = 7; } // PartitionSpec is the spec for volume partitioning. @@ -211,5 +213,7 @@ message VolumeStatusSpec { string pretty_size = 13; repeated string encryption_failed_syncs = 14; MountSpec mount_spec = 15; + talos.resource.definitions.enums.BlockVolumeType type = 16; + repeated string configured_encryption_keys = 17; } diff --git a/go.mod b/go.mod index 8f0315062..8a1a3f2ef 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/containernetworking/plugins v1.6.2 github.com/coredns/coredns v1.11.3 github.com/coreos/go-iptables v0.8.0 - github.com/cosi-project/runtime v0.10.0 + github.com/cosi-project/runtime v0.10.1 github.com/distribution/reference v0.6.0 github.com/docker/cli v28.0.1+incompatible github.com/docker/docker v28.0.1+incompatible @@ -272,13 +272,13 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.6.9 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/gosuri/uilive v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect diff --git a/go.sum b/go.sum index 672bcd92f..9b9ec6ca6 100644 --- a/go.sum +++ b/go.sum @@ -164,8 +164,8 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cosi-project/runtime v0.10.0 h1:8CvXq5TtFIJY4/PZQh2iCgZMs8hxOLzoU64abs6k5dc= -github.com/cosi-project/runtime v0.10.0/go.mod h1:ZQGhCKF7YD42wFlZdw5y9RVIjlbviIyn0cYnmLdQ3Qs= +github.com/cosi-project/runtime v0.10.1 h1:s3LWW3UZgORKSINhNFd1G0RZevAatQ01+70cIWdKK7c= +github.com/cosi-project/runtime v0.10.1/go.mod h1:AdQvVoG6kfhGwWEqsFxndynrp1jr8KNoYj75dHJCxcE= github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -321,8 +321,9 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= github.com/google/go-tpm v0.9.3 h1:+yx0/anQuGzi+ssRqeD6WpXjW2L/V0dItUayO0i9sRc= @@ -359,8 +360,8 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:Fecb github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.2 h1:VpMASoqIPXLWWdkkbTA9ZyoP8J9Jw0M7S82qEhkALFs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.2/go.mod h1:FYBptsOc6KxMvX44fK7+t/bQcDcDI4UGibbAuuAnRu4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go b/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go index c435b2f28..3776e391d 100644 --- a/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go +++ b/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go @@ -566,6 +566,7 @@ type ResetOptions struct { *machine.ResetRequest systemDiskTargets []*partition.VolumeWipeTarget + systemDiskPaths []string } // GetSystemDiskTargets implements runtime.ResetOptions interface. @@ -577,6 +578,11 @@ func (opt *ResetOptions) GetSystemDiskTargets() []runtime.PartitionTarget { return xslices.Map(opt.systemDiskTargets, func(t *partition.VolumeWipeTarget) runtime.PartitionTarget { return t }) } +// GetSystemDiskPaths implements runtime.ResetOptions interface. +func (opt *ResetOptions) GetSystemDiskPaths() []string { + return opt.systemDiskPaths +} + // String implements runtime.ResetOptions interface. func (opt *ResetOptions) String() string { return strings.Join(xslices.Map(opt.systemDiskTargets, func(t *partition.VolumeWipeTarget) string { return t.String() }), ", ") @@ -584,7 +590,7 @@ func (opt *ResetOptions) String() string { // Reset resets the node. // -//nolint:gocyclo +//nolint:gocyclo,cyclop func (s *Server) Reset(ctx context.Context, in *machine.ResetRequest) (reply *machine.ResetResponse, err error) { actorID := uuid.New().String() @@ -656,6 +662,13 @@ func (s *Server) Reset(ctx context.Context, in *machine.ResetRequest) (reply *ma } } + if in.Mode != machine.ResetRequest_USER_DISKS && len(in.GetSystemPartitionsToWipe()) == 0 { + opts.systemDiskPaths, err = block.GetSystemDiskPaths(ctx, s.Controller.Runtime().State().V1Alpha2().Resources()) + if err != nil { + return nil, fmt.Errorf("system disk paths lookup failed: %w", err) + } + } + resetCtx := context.WithValue(context.Background(), runtime.ActorIDCtxKey{}, actorID) go func() { diff --git a/internal/app/machined/pkg/controllers/block/internal/volumes/encrypt.go b/internal/app/machined/pkg/controllers/block/internal/volumes/encrypt.go index 537b0a4c5..ef6aa9335 100644 --- a/internal/app/machined/pkg/controllers/block/internal/volumes/encrypt.go +++ b/internal/app/machined/pkg/controllers/block/internal/volumes/encrypt.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "path/filepath" + "slices" "time" "github.com/siderolabs/gen/xerrors" @@ -27,6 +28,8 @@ func HandleEncryption(ctx context.Context, logger *zap.Logger, volumeContext Man volumeContext.Status.Phase = block.VolumePhasePrepared volumeContext.Status.MountLocation = volumeContext.Status.Location volumeContext.Status.EncryptionProvider = block.EncryptionProviderNone + volumeContext.Status.EncryptionFailedSyncs = nil + volumeContext.Status.ConfiguredEncryptionKeys = nil return nil case block.EncryptionProviderLUKS2: @@ -46,6 +49,8 @@ func HandleEncryption(ctx context.Context, logger *zap.Logger, volumeContext Man const encryptionTimeout = time.Minute // HandleEncryptionWithHandler makes sure the encryption for the volumes is handled appropriately. +// +//nolint:gocyclo func HandleEncryptionWithHandler(ctx context.Context, logger *zap.Logger, volumeContext ManagerContext, handler *encryption.Handler) error { ctx, cancel := context.WithTimeout(ctx, encryptionTimeout) defer cancel() @@ -108,5 +113,17 @@ func HandleEncryptionWithHandler(ctx context.Context, logger *zap.Logger, volume volumeContext.Status.EncryptionProvider = volumeContext.Cfg.TypedSpec().Encryption.Provider volumeContext.Status.EncryptionFailedSyncs = failedSyncs + volumeContext.Status.ConfiguredEncryptionKeys = nil + + for _, key := range volumeContext.Cfg.TypedSpec().Encryption.Keys { + provider := key.Type.String() + + if slices.Index(volumeContext.Status.ConfiguredEncryptionKeys, provider) == -1 { + volumeContext.Status.ConfiguredEncryptionKeys = append(volumeContext.Status.ConfiguredEncryptionKeys, provider) + } + } + + slices.Sort(volumeContext.Status.ConfiguredEncryptionKeys) + return nil } diff --git a/internal/app/machined/pkg/controllers/block/internal/volumes/volumes.go b/internal/app/machined/pkg/controllers/block/internal/volumes/volumes.go index 699e38821..dffc27583 100644 --- a/internal/app/machined/pkg/controllers/block/internal/volumes/volumes.go +++ b/internal/app/machined/pkg/controllers/block/internal/volumes/volumes.go @@ -88,5 +88,5 @@ type ManagerContext struct { DevicesReady bool PreviousWaveProvisioned bool GetSystemInformation func(context.Context) (*hardware.SystemInformation, error) - Lifecycle *block.VolumeLifecycle + ShouldCloseVolume bool } diff --git a/internal/app/machined/pkg/controllers/block/mount.go b/internal/app/machined/pkg/controllers/block/mount.go index ebca640eb..454842f02 100644 --- a/internal/app/machined/pkg/controllers/block/mount.go +++ b/internal/app/machined/pkg/controllers/block/mount.go @@ -196,10 +196,10 @@ func (ctrl *MountController) Run(ctx context.Context, r controller.Runtime, logg if !ok { var opts []mount.NewPointOption - // [TODO]: need to support more mount options: - // * proj quota (static) - - opts = append(opts, mount.WithSelinuxLabel(volumeStatus.TypedSpec().MountSpec.SelinuxLabel)) + opts = append(opts, + mount.WithProjectQuota(volumeStatus.TypedSpec().MountSpec.ProjectQuotaSupport), + mount.WithSelinuxLabel(volumeStatus.TypedSpec().MountSpec.SelinuxLabel), + ) if mountRequest.TypedSpec().ReadOnly { opts = append(opts, mount.WithReadonly()) @@ -251,7 +251,9 @@ func (ctrl *MountController) Run(ctx context.Context, r controller.Runtime, logg mountStatus.TypedSpec().Source = mountSource mountStatus.TypedSpec().Target = mountTarget mountStatus.TypedSpec().Filesystem = mountFilesystem + mountStatus.TypedSpec().EncryptionProvider = volumeStatus.TypedSpec().EncryptionProvider mountStatus.TypedSpec().ReadOnly = mountRequest.TypedSpec().ReadOnly + mountStatus.TypedSpec().ProjectQuotaSupport = volumeStatus.TypedSpec().MountSpec.ProjectQuotaSupport return nil }, diff --git a/internal/app/machined/pkg/controllers/block/volume_config.go b/internal/app/machined/pkg/controllers/block/volume_config.go index 035e8cbd7..6d7ed4d80 100644 --- a/internal/app/machined/pkg/controllers/block/volume_config.go +++ b/internal/app/machined/pkg/controllers/block/volume_config.go @@ -232,8 +232,9 @@ func (ctrl *VolumeConfigController) manageEphemeral(config cfg.Config) func(vc * } vc.TypedSpec().Mount = block.MountSpec{ - TargetPath: constants.EphemeralMountPoint, - SelinuxLabel: constants.EphemeralSelinuxLabel, + TargetPath: constants.EphemeralMountPoint, + SelinuxLabel: constants.EphemeralSelinuxLabel, + ProjectQuotaSupport: config.Machine().Features().DiskQuotaSupportEnabled(), } vc.TypedSpec().Locator = block.LocatorSpec{ diff --git a/internal/app/machined/pkg/controllers/block/volume_manager.go b/internal/app/machined/pkg/controllers/block/volume_manager.go index 92b3d5c71..4f0a58728 100644 --- a/internal/app/machined/pkg/controllers/block/volume_manager.go +++ b/internal/app/machined/pkg/controllers/block/volume_manager.go @@ -23,6 +23,7 @@ import ( "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/block/internal/volumes" blockpb "github.com/siderolabs/talos/pkg/machinery/api/resource/definitions/block" + "github.com/siderolabs/talos/pkg/machinery/constants" "github.com/siderolabs/talos/pkg/machinery/proto" "github.com/siderolabs/talos/pkg/machinery/resources/block" "github.com/siderolabs/talos/pkg/machinery/resources/hardware" @@ -45,6 +46,11 @@ func (ctrl *VolumeManagerController) Inputs() []controller.Input { Type: block.VolumeConfigType, Kind: controller.InputStrong, }, + { + Namespace: block.NamespaceName, + Type: block.VolumeStatusType, + Kind: controller.InputDestroyReady, + }, { Namespace: block.NamespaceName, Type: block.DiscoveredVolumeType, @@ -230,17 +236,15 @@ func (ctrl *VolumeManagerController) Run(ctx context.Context, r controller.Runti return fmt.Errorf("error fetching volume statuses: %w", err) } - volumeConfigIDs := xslices.ToSet(safe.ToSlice(volumeConfigList, func(vc *block.VolumeConfig) resource.ID { return vc.Metadata().ID() })) - volumeStatuses := xslices.ToMap( safe.ToSlice(volumeStatusList, func(vs *block.VolumeStatus) *block.VolumeStatus { return vs }), - func(vs *block.VolumeStatus) (resource.ID, *block.VolumeStatusSpec) { - return vs.Metadata().ID(), vs.TypedSpec() + func(vs *block.VolumeStatus) (resource.ID, *block.VolumeStatus) { + return vs.Metadata().ID(), vs }, ) if volumeStatuses == nil { - volumeStatuses = map[resource.ID]*block.VolumeStatusSpec{} + volumeStatuses = map[resource.ID]*block.VolumeStatus{} } // ensure all volume configs have our finalizers @@ -249,36 +253,14 @@ func (ctrl *VolumeManagerController) Run(ctx context.Context, r controller.Runti continue } - if vc.Metadata().Finalizers().Has(ctrl.Name()) { - continue - } - - if err = r.AddFinalizer(ctx, vc.Metadata(), ctrl.Name()); err != nil { - return fmt.Errorf("error adding finalizer to volume configuration: %w", err) - } - } - - // remove statuses for volume configs that no longer exist - for id := range volumeStatuses { - if _, exists := volumeConfigIDs[id]; !exists { - delete(volumeStatuses, id) - - if err := r.Destroy(ctx, block.NewVolumeStatus(block.NamespaceName, id).Metadata()); err != nil { - return fmt.Errorf("error destroying volume status: %w", err) + if !vc.Metadata().Finalizers().Has(ctrl.Name()) { + if err = r.AddFinalizer(ctx, vc.Metadata(), ctrl.Name()); err != nil { + return fmt.Errorf("error adding finalizer to volume configuration: %w", err) } } } - // fill in statuses for volume configs that don't have a status yet - for id := range volumeConfigIDs { - if _, exists := volumeStatuses[id]; !exists { - volumeStatuses[id] = &block.VolumeStatusSpec{ - Phase: block.VolumePhaseWaiting, - } - } - } - - volumeConfigs := safe.ToSlice(volumeConfigList, func(vc *block.VolumeConfig) *block.VolumeConfig { return vc }) + volumeConfigs := safe.ToSlice(volumeConfigList, identity) // re-sort volume configs by provisioning wave slices.SortStableFunc(volumeConfigs, volumes.CompareVolumeConfigs) @@ -297,19 +279,49 @@ func (ctrl *VolumeManagerController) Run(ctx context.Context, r controller.Runti volumeStatus := volumeStatuses[vc.Metadata().ID()] volumeLogger := logger.With(zap.String("volume", vc.Metadata().ID())) - if vc.Metadata().Phase() != resource.PhaseRunning { - // [TODO]: handle me later - continue + // figure out if we are tearing down this volume or building it + tearingDown := (volumeStatus != nil && volumeStatus.Metadata().Phase() == resource.PhaseTearingDown) || // we started tearing down the volume, so finish doing so + vc.Metadata().Phase() == resource.PhaseTearingDown || // volume config is being torn down + volumeLifecycle.Metadata().Phase() == resource.PhaseTearingDown // global volume lifecycle requires all volumes to be torn down + + // volume status doesn't exist yet, figure out what to do + if volumeStatus == nil { + if tearingDown { + // happy case, we don't need to progress this volume + if vc.Metadata().Finalizers().Has(ctrl.Name()) { + if err = r.RemoveFinalizer(ctx, vc.Metadata(), ctrl.Name()); err != nil { + return fmt.Errorf("error removing finalizer from volume configuration: %w", err) + } + } + + continue + } + + // create a stub volume status + volumeStatus = block.NewVolumeStatus(block.NamespaceName, vc.Metadata().ID()) + volumeStatus.TypedSpec().Phase = block.VolumePhaseWaiting + volumeStatus.TypedSpec().Type = vc.TypedSpec().Type + volumeStatuses[vc.Metadata().ID()] = volumeStatus } - prevPhase := volumeStatus.Phase + if tearingDown && volumeStatus.Metadata().Phase() != resource.PhaseTearingDown { + // volume status is not yet in the tearing down phase, so move it there + _, err = r.Teardown(ctx, volumeStatus.Metadata()) + if err != nil { + return fmt.Errorf("error tearing down volume status: %w", err) + } + } + + shouldCloseVolume := tearingDown && volumeStatus.Metadata().Finalizers().Empty() // we can start closing volume as soon as all finalizers are gone, so the volume is not e.g. mounted + + prevPhase := volumeStatus.TypedSpec().Phase if err = ctrl.processVolumeConfig( ctx, volumeLogger, volumes.ManagerContext{ Cfg: vc, - Status: volumeStatus, + Status: volumeStatus.TypedSpec(), DiscoveredVolumes: discoveredVolumesSpecs, Disks: diskSpecs, DevicesReady: devicesReady, @@ -326,60 +338,70 @@ func (ctrl *VolumeManagerController) Run(ctx context.Context, r controller.Runti return systemInfo, nil }, - Lifecycle: volumeLifecycle, + ShouldCloseVolume: shouldCloseVolume, }, ); err != nil { - volumeStatus.PreFailPhase = volumeStatus.Phase - volumeStatus.Phase = block.VolumePhaseFailed - volumeStatus.ErrorMessage = err.Error() + volumeStatus.TypedSpec().PreFailPhase = volumeStatus.TypedSpec().Phase + volumeStatus.TypedSpec().Phase = block.VolumePhaseFailed + volumeStatus.TypedSpec().ErrorMessage = err.Error() if xerrors.TagIs[volumes.Retryable](err) { shouldRetry = true } } else { - volumeStatus.ErrorMessage = "" - volumeStatus.PreFailPhase = block.VolumePhase(0) + volumeStatus.TypedSpec().ErrorMessage = "" + volumeStatus.TypedSpec().PreFailPhase = block.VolumePhase(0) } - if volumeStatus.Phase != block.VolumePhaseReady { + if volumeStatus.TypedSpec().Phase != block.VolumePhaseReady { fullyProvisionedWave = vc.TypedSpec().Provisioning.Wave - 1 } - if prevPhase != volumeStatus.Phase || err != nil { + if prevPhase != volumeStatus.TypedSpec().Phase || err != nil { fields := []zap.Field{ - zap.String("phase", fmt.Sprintf("%s -> %s", prevPhase, volumeStatus.Phase)), + zap.String("phase", fmt.Sprintf("%s -> %s", prevPhase, volumeStatus.TypedSpec().Phase)), zap.Error(err), } - if volumeStatus.Location != "" { - fields = append(fields, zap.String("location", volumeStatus.Location)) + if volumeStatus.TypedSpec().Location != "" { + fields = append(fields, zap.String("location", volumeStatus.TypedSpec().Location)) } - if volumeStatus.MountLocation != "" && volumeStatus.MountLocation != volumeStatus.Location { - fields = append(fields, zap.String("mountLocation", volumeStatus.MountLocation)) + if volumeStatus.TypedSpec().MountLocation != "" && volumeStatus.TypedSpec().MountLocation != volumeStatus.TypedSpec().Location { + fields = append(fields, zap.String("mountLocation", volumeStatus.TypedSpec().MountLocation)) } - if volumeStatus.ParentLocation != "" { - fields = append(fields, zap.String("parentLocation", volumeStatus.ParentLocation)) + if volumeStatus.TypedSpec().ParentLocation != "" { + fields = append(fields, zap.String("parentLocation", volumeStatus.TypedSpec().ParentLocation)) } - if len(volumeStatus.EncryptionFailedSyncs) > 0 { - fields = append(fields, zap.Strings("encryptionFailedSyncs", volumeStatus.EncryptionFailedSyncs)) + if len(volumeStatus.TypedSpec().EncryptionFailedSyncs) > 0 { + fields = append(fields, zap.Strings("encryptionFailedSyncs", volumeStatus.TypedSpec().EncryptionFailedSyncs)) } volumeLogger.Info("volume status", fields...) } - allClosed = allClosed && volumeStatus.Phase == block.VolumePhaseClosed + // when closing, ignore META volume, we want it to stay longer, so no problem if is not closed yet + allClosed = allClosed && (volumeStatus.TypedSpec().Phase == block.VolumePhaseClosed || vc.Metadata().ID() == constants.MetaPartitionLabel) + + if shouldCloseVolume && volumeStatus.TypedSpec().Phase == block.VolumePhaseClosed { + // we can destroy the volume status now + if err = r.Destroy(ctx, volumeStatus.Metadata()); err != nil { + return fmt.Errorf("error destroying volume status: %w", err) + } + + delete(volumeStatuses, volumeStatus.Metadata().ID()) + } } // update statuses - for id, spec := range volumeStatuses { + for id, newVs := range volumeStatuses { if err = safe.WriterModify(ctx, r, block.NewVolumeStatus(block.NamespaceName, id), func(vs *block.VolumeStatus) error { - *vs.TypedSpec() = *spec + *vs.TypedSpec() = *newVs.TypedSpec() return nil - }); err != nil { + }, controller.WithExpectedPhaseAny()); err != nil { return fmt.Errorf("error updating volume status: %w", err) } } @@ -410,10 +432,8 @@ func (ctrl *VolumeManagerController) Run(ctx context.Context, r controller.Runti func (ctrl *VolumeManagerController) processVolumeConfig(ctx context.Context, logger *zap.Logger, volumeContext volumes.ManagerContext) error { prevPhase := volumeContext.Status.Phase - closingPhase := volumeContext.Lifecycle.Metadata().Phase() == resource.PhaseTearingDown - for { - if !closingPhase { + if !volumeContext.ShouldCloseVolume { // normal state machine switch volumeContext.Status.Phase { case block.VolumePhaseReady: diff --git a/internal/app/machined/pkg/controllers/runtime/mount_status.go b/internal/app/machined/pkg/controllers/runtime/mount_status.go new file mode 100644 index 000000000..795ce52e5 --- /dev/null +++ b/internal/app/machined/pkg/controllers/runtime/mount_status.go @@ -0,0 +1,104 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package runtime + +import ( + "context" + "fmt" + + "github.com/cosi-project/runtime/pkg/controller" + "github.com/cosi-project/runtime/pkg/safe" + "github.com/cosi-project/runtime/pkg/state" + "go.uber.org/zap" + + "github.com/siderolabs/talos/pkg/machinery/resources/block" + "github.com/siderolabs/talos/pkg/machinery/resources/runtime" +) + +// MountStatusController transforms block.MountStatus resources into legacy v1alpha1.MountStatus. +// +// It only exists to provide backwards compatibility with legacy consumers. +type MountStatusController struct{} + +// Name implements controller.Controller interface. +func (ctrl *MountStatusController) Name() string { + return "runtime.MountStatusController" +} + +// Inputs implements controller.Controller interface. +func (ctrl *MountStatusController) Inputs() []controller.Input { + return []controller.Input{ + { + Namespace: block.NamespaceName, + Type: block.MountStatusType, + Kind: controller.InputWeak, + }, + { + Namespace: block.NamespaceName, + Type: block.VolumeStatusType, + Kind: controller.InputWeak, + }, + } +} + +// Outputs implements controller.Controller interface. +func (ctrl *MountStatusController) Outputs() []controller.Output { + return []controller.Output{ + { + Type: runtime.MountStatusType, + Kind: controller.OutputExclusive, + }, + } +} + +// Run implements controller.Controller interface. +// +//nolint:gocyclo +func (ctrl *MountStatusController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) error { + for { + select { + case <-r.EventCh(): + case <-ctx.Done(): + return nil + } + + mountStatuses, err := safe.ReaderListAll[*block.MountStatus](ctx, r) + if err != nil { + return fmt.Errorf("failed to read mount statuses: %w", err) + } + + r.StartTrackingOutputs() + + for mountStatus := range mountStatuses.All() { + volumeStatus, err := safe.ReaderGetByID[*block.VolumeStatus](ctx, r, mountStatus.TypedSpec().Spec.VolumeID) + if err != nil && !state.IsNotFoundError(err) { + return fmt.Errorf("failed to get volume status %q: %w", mountStatus.TypedSpec().Spec.VolumeID, err) + } + + if volumeStatus.TypedSpec().Type != block.VolumeTypePartition && volumeStatus.TypedSpec().Type != block.VolumeTypeDisk { + // legacy volume statuses shouldn't show up for non-partition/disk volumes + continue + } + + if err = safe.WriterModify(ctx, r, runtime.NewMountStatus(runtime.NamespaceName, volumeStatus.Metadata().ID()), + func(res *runtime.MountStatus) error { + res.TypedSpec().Source = mountStatus.TypedSpec().Source + res.TypedSpec().Target = mountStatus.TypedSpec().Target + res.TypedSpec().FilesystemType = volumeStatus.TypedSpec().Filesystem.String() + res.TypedSpec().Encrypted = volumeStatus.TypedSpec().EncryptionProvider != block.EncryptionProviderNone + res.TypedSpec().EncryptionProviders = volumeStatus.TypedSpec().ConfiguredEncryptionKeys + + return nil + }, + ); err != nil { + return fmt.Errorf("failed to write mount status: %w", err) + } + } + + if err := safe.CleanupOutputs[*runtime.MountStatus](ctx, r); err != nil { + return fmt.Errorf("failed to cleanup mount statuses: %w", err) + } + } +} diff --git a/internal/app/machined/pkg/runtime/sequencer.go b/internal/app/machined/pkg/runtime/sequencer.go index 1e44fea30..8c15f2a7c 100644 --- a/internal/app/machined/pkg/runtime/sequencer.go +++ b/internal/app/machined/pkg/runtime/sequencer.go @@ -132,6 +132,7 @@ type ResetOptions interface { GetMode() machine.ResetRequest_WipeMode GetUserDisksToWipe() []string GetSystemDiskTargets() []PartitionTarget + GetSystemDiskPaths() []string } // PartitionTarget provides interface to the disk partition. diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go index da68b5f52..48f6dc6f3 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go @@ -27,7 +27,6 @@ import ( "github.com/foxboron/go-uefi/efi" "github.com/hashicorp/go-multierror" pprocfs "github.com/prometheus/procfs" - "github.com/siderolabs/gen/maps" "github.com/siderolabs/gen/xslices" "github.com/siderolabs/go-blockdevice/v2/block" "github.com/siderolabs/go-cmd/pkg/cmd" @@ -1257,12 +1256,21 @@ func ResetSystemDiskPartitions(seq runtime.Sequence, _ any) (runtime.TaskExecuti } if *wipeStr == "system" { - resetSystemDisk, _ := ResetSystemDisk(seq, nil) - return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) error { + systemDiskPaths, err := blockres.GetSystemDiskPaths(ctx, r.State().V1Alpha2().Resources()) + if err != nil { + return err + } + + targets := targets{ + systemDiskPaths: systemDiskPaths, + } + logger.Printf("resetting system disks") - err := resetSystemDisk(ctx, logger, r) + resetSystemDisk, _ := ResetSystemDisk(seq, targets) + + err = resetSystemDisk(ctx, logger, r) if err != nil { logger.Printf("resetting system disks failed") @@ -1302,45 +1310,14 @@ func ResetSystemDiskPartitions(seq runtime.Sequence, _ any) (runtime.TaskExecuti // ResetSystemDisk represents the task to reset the system disk. // //nolint:gocyclo -func ResetSystemDisk(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) { +func ResetSystemDisk(_ runtime.Sequence, data any) (runtime.TaskExecutionFunc, string) { return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) error { - systemDisks := map[string]struct{}{} - - // fetch system disk (where Talos is installed) - systemDisk, err := blockres.GetSystemDisk(ctx, r.State().V1Alpha2().Resources()) - if err != nil { - return err + in, ok := data.(SystemDiskTargets) + if !ok { + return errors.New("unexpected runtime data") } - if systemDisk != nil { - systemDisks[systemDisk.DevPath] = struct{}{} - } - - // fetch additional system volumes (which might be on the same or other disks) - for _, volumeID := range []string{constants.StatePartitionLabel, constants.EphemeralPartitionLabel} { - volumeStatus, err := safe.ReaderGetByID[*blockres.VolumeStatus](ctx, r.State().V1Alpha2().Resources(), volumeID) - if err != nil { - if state.IsNotFoundError(err) { - continue - } - - return err - } - - if volumeStatus.TypedSpec().ParentLocation != "" { - systemDisks[volumeStatus.TypedSpec().ParentLocation] = struct{}{} - } else if volumeStatus.TypedSpec().Location != "" { - systemDisks[volumeStatus.TypedSpec().Location] = struct{}{} - } - } - - if len(systemDisks) == 0 { - return nil - } - - systemDiskPaths := maps.Keys(systemDisks) - - for _, systemDiskPath := range systemDiskPaths { + for _, systemDiskPath := range in.GetSystemDiskPaths() { if err := func(devPath string) error { logger.Printf("wiping system disk %s", devPath) @@ -1350,7 +1327,7 @@ func ResetSystemDisk(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) } if err = dev.RetryLockWithTimeout(ctx, true, time.Minute); err != nil { - return fmt.Errorf("failed to lock device %s: %w", systemDisk.DevPath, err) + return fmt.Errorf("failed to lock device %s: %w", devPath, err) } defer dev.Close() //nolint:errcheck @@ -1408,12 +1385,19 @@ func ResetUserDisks(_ runtime.Sequence, data any) (runtime.TaskExecutionFunc, st type targets struct { systemDiskTargets []*partition.VolumeWipeTarget + systemDiskPaths []string } +var _ SystemDiskTargets = targets{} + func (opt targets) GetSystemDiskTargets() []runtime.PartitionTarget { return xslices.Map(opt.systemDiskTargets, func(t *partition.VolumeWipeTarget) runtime.PartitionTarget { return t }) } +func (opt targets) GetSystemDiskPaths() []string { + return opt.systemDiskPaths +} + func (opt targets) String() string { return strings.Join(xslices.Map(opt.systemDiskTargets, func(t *partition.VolumeWipeTarget) string { return t.String() }), ", ") } @@ -1464,6 +1448,7 @@ func parseTargets(ctx context.Context, r runtime.Runtime, wipeStr string) (Syste // It's a subset of [runtime.ResetOptions]. type SystemDiskTargets interface { GetSystemDiskTargets() []runtime.PartitionTarget + GetSystemDiskPaths() []string fmt.Stringer } @@ -1713,19 +1698,46 @@ func UnmountStatePartition(runtime.Sequence, any) (runtime.TaskExecutionFunc, st // MountEphemeralPartition mounts the ephemeral partition. func MountEphemeralPartition(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) { return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) error { - if _, err := waitForVolumeReady(ctx, r, constants.EphemeralPartitionLabel); err != nil { - return err + mountRequest := blockres.NewVolumeMountRequest(blockres.NamespaceName, constants.EphemeralPartitionLabel) + mountRequest.TypedSpec().VolumeID = constants.EphemeralPartitionLabel + mountRequest.TypedSpec().Requester = "sequencer" + + if err := r.State().V1Alpha2().Resources().Create(ctx, mountRequest); err != nil { + return fmt.Errorf("failed to create EPHEMERAL mount request: %w", err) } - return mount.SystemPartitionMount(ctx, r, logger, constants.EphemeralPartitionLabel, false, - mountv2.WithProjectQuota(r.Config().Machine().Features().DiskQuotaSupportEnabled())) + if _, err := r.State().V1Alpha2().Resources().WatchFor( + ctx, + blockres.NewVolumeMountStatus(blockres.NamespaceName, constants.EphemeralPartitionLabel).Metadata(), + state.WithEventTypes(state.Created, state.Updated), + ); err != nil { + return fmt.Errorf("failed to wait for EPHEMERAL to be mounted: %w", err) + } + + return nil }, "mountEphemeralPartition" } // UnmountEphemeralPartition unmounts the ephemeral partition. func UnmountEphemeralPartition(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) { - return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) { - return mount.SystemPartitionUnmount(r, logger, constants.EphemeralPartitionLabel) + return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) error { + mountRequest := blockres.NewVolumeMountRequest(blockres.NamespaceName, constants.EphemeralPartitionLabel).Metadata() + + _, err := r.State().V1Alpha2().Resources().Teardown(ctx, mountRequest) + if err != nil { + if state.IsNotFoundError(err) { + return nil + } + + return fmt.Errorf("failed to teardown EPHEMERAL mount request: %w", err) + } + + _, err = r.State().V1Alpha2().Resources().WatchFor(ctx, mountRequest, state.WithFinalizerEmpty()) + if err != nil { + return fmt.Errorf("failed to wait for EPHEMERAL teardown: %w", err) + } + + return r.State().V1Alpha2().Resources().Destroy(ctx, mountRequest) }, "unmountEphemeralPartition" } diff --git a/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_controller.go b/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_controller.go index bf26ee26f..b868a5b64 100644 --- a/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_controller.go +++ b/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_controller.go @@ -349,6 +349,7 @@ func (ctrl *Controller) Run(ctx context.Context, drainer *runtime.Drainer) error &runtimecontrollers.MachineStatusPublisherController{ V1Alpha1Events: ctrl.v1alpha1Runtime.Events(), }, + &runtimecontrollers.MountStatusController{}, &runtimecontrollers.SecurityStateController{ V1Alpha1Mode: ctrl.v1alpha1Runtime.State().Platform().Mode(), }, diff --git a/internal/app/machined/pkg/system/integration_test.go b/internal/app/machined/pkg/system/integration_test.go index 3ae24355a..6d32ed78a 100644 --- a/internal/app/machined/pkg/system/integration_test.go +++ b/internal/app/machined/pkg/system/integration_test.go @@ -70,6 +70,10 @@ func (TestService) DependsOn(runtime.Runtime) []string { return nil } +func (TestService) Volumes() []string { + return nil +} + func TestRestartService(t *testing.T) { deadline, ok := t.Deadline() if !ok { diff --git a/internal/app/machined/pkg/system/mocks_test.go b/internal/app/machined/pkg/system/mocks_test.go index 4795a67ab..7b8358d76 100644 --- a/internal/app/machined/pkg/system/mocks_test.go +++ b/internal/app/machined/pkg/system/mocks_test.go @@ -64,6 +64,10 @@ func (m *MockService) DependsOn(runtime.Runtime) []string { return m.dependencies } +func (m *MockService) Volumes() []string { + return nil +} + type MockHealthcheckedService struct { MockService diff --git a/internal/app/machined/pkg/system/service.go b/internal/app/machined/pkg/system/service.go index 428762be0..9c65af683 100644 --- a/internal/app/machined/pkg/system/service.go +++ b/internal/app/machined/pkg/system/service.go @@ -29,6 +29,8 @@ type Service interface { Condition(runtime.Runtime) conditions.Condition // DependsOn returns list of service IDs this service depends on. DependsOn(runtime.Runtime) []string + // Volumes returns a list of volume IDs the service needs. + Volumes() []string } // HealthcheckedService is a service which provides health check. diff --git a/internal/app/machined/pkg/system/service_runner.go b/internal/app/machined/pkg/system/service_runner.go index deb2f785e..dc6c101f4 100644 --- a/internal/app/machined/pkg/system/service_runner.go +++ b/internal/app/machined/pkg/system/service_runner.go @@ -212,16 +212,39 @@ func (svcrunner *ServiceRunner) Run(notifyChannels ...chan<- struct{}) error { condition := svcrunner.service.Condition(svcrunner.runtime) - dependencies := svcrunner.service.DependsOn(svcrunner.runtime) - if len(dependencies) > 0 { + if dependencies := svcrunner.service.DependsOn(svcrunner.runtime); len(dependencies) > 0 { serviceConditions := xslices.Map(dependencies, func(dep string) conditions.Condition { return waitForService(instance, StateEventUp, dep) }) serviceDependencies := conditions.WaitForAll(serviceConditions...) - if condition != nil { - condition = conditions.WaitForAll(serviceDependencies, condition) - } else { - condition = serviceDependencies + condition = conditions.WaitForAll(serviceDependencies, condition) + } + + if volumeIDs := svcrunner.service.Volumes(); len(volumeIDs) > 0 && !svcrunner.runtime.State().Platform().Mode().InContainer() { + // create volume mount request for each volume requested + volumeRequestIDs := make([]string, 0, len(volumeIDs)) + + for _, volumeID := range volumeIDs { + requestID, err := svcrunner.createVolumeMountRequest(ctx, volumeID) + if err != nil { + return err + } + + volumeRequestIDs = append(volumeRequestIDs, requestID) } + + // the condition will wait for volume mount statuses, and put a finalizer on it + volumeConditions := xslices.Map(volumeRequestIDs, func(requestID string) conditions.Condition { + return WaitForVolumeToBeMounted(svcrunner.runtime.State().V1Alpha2().Resources(), requestID) + }) + + condition = conditions.WaitForAll(conditions.WaitForAll(volumeConditions...), condition) + + // cleanup volume mounts + defer func() { + if err := svcrunner.deleteVolumeMountRequest(ctx, volumeRequestIDs); err != nil { + svcrunner.UpdateState(ctx, events.StateFailed, "Failed to clean up volumes: %v", err) + } + }() } if condition != nil { diff --git a/internal/app/machined/pkg/system/services/apid.go b/internal/app/machined/pkg/system/services/apid.go index f8587fe4c..c78234d14 100644 --- a/internal/app/machined/pkg/system/services/apid.go +++ b/internal/app/machined/pkg/system/services/apid.go @@ -134,6 +134,11 @@ func (o *APID) DependsOn(runtime.Runtime) []string { return []string{"containerd"} } +// Volumes implements the Service interface. +func (o *APID) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (o *APID) Runner(r runtime.Runtime) (runner.Runner, error) { // Ensure socket dir exists diff --git a/internal/app/machined/pkg/system/services/auditd.go b/internal/app/machined/pkg/system/services/auditd.go index c2a54731f..a856b6006 100644 --- a/internal/app/machined/pkg/system/services/auditd.go +++ b/internal/app/machined/pkg/system/services/auditd.go @@ -50,6 +50,11 @@ func (s *Auditd) DependsOn(runtime.Runtime) []string { return nil } +// Volumes implements the Service interface. +func (s *Auditd) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (s *Auditd) Runner(r runtime.Runtime) (runner.Runner, error) { return goroutine.NewRunner(r, auditdServiceID, auditd.Main, runner.WithLoggingManager(r.Logging())), nil diff --git a/internal/app/machined/pkg/system/services/containerd.go b/internal/app/machined/pkg/system/services/containerd.go index 0061d0793..5fc0df09e 100644 --- a/internal/app/machined/pkg/system/services/containerd.go +++ b/internal/app/machined/pkg/system/services/containerd.go @@ -78,6 +78,11 @@ func (c *Containerd) DependsOn(runtime.Runtime) []string { return nil } +// Volumes implements the Service interface. +func (c *Containerd) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (c *Containerd) Runner(r runtime.Runtime) (runner.Runner, error) { // Set the process arguments. diff --git a/internal/app/machined/pkg/system/services/cri.go b/internal/app/machined/pkg/system/services/cri.go index bb532ecbd..6791488e0 100644 --- a/internal/app/machined/pkg/system/services/cri.go +++ b/internal/app/machined/pkg/system/services/cri.go @@ -80,6 +80,11 @@ func (c *CRI) DependsOn(runtime.Runtime) []string { return nil } +// Volumes implements the Service interface. +func (c *CRI) Volumes() []string { + return []string{constants.EphemeralPartitionLabel} +} + // Runner implements the Service interface. func (c *CRI) Runner(r runtime.Runtime) (runner.Runner, error) { // Set the process arguments. diff --git a/internal/app/machined/pkg/system/services/dashboard.go b/internal/app/machined/pkg/system/services/dashboard.go index 921bd287b..8642ded0f 100644 --- a/internal/app/machined/pkg/system/services/dashboard.go +++ b/internal/app/machined/pkg/system/services/dashboard.go @@ -50,6 +50,11 @@ func (d *Dashboard) DependsOn(_ runtime.Runtime) []string { return []string{machinedServiceID} } +// Volumes implements the Service interface. +func (d *Dashboard) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (d *Dashboard) Runner(r runtime.Runtime) (runner.Runner, error) { tty := fmt.Sprintf("/dev/tty%d", constants.DashboardTTY) diff --git a/internal/app/machined/pkg/system/services/etcd.go b/internal/app/machined/pkg/system/services/etcd.go index 86b4ccb00..83be96e72 100644 --- a/internal/app/machined/pkg/system/services/etcd.go +++ b/internal/app/machined/pkg/system/services/etcd.go @@ -184,6 +184,11 @@ func (e *Etcd) DependsOn(runtime.Runtime) []string { return []string{"cri"} } +// Volumes implements the Service interface. +func (e *Etcd) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (e *Etcd) Runner(r runtime.Runtime) (runner.Runner, error) { // Set the process arguments. diff --git a/internal/app/machined/pkg/system/services/extension.go b/internal/app/machined/pkg/system/services/extension.go index 4e3ac0827..c6de6f1b6 100644 --- a/internal/app/machined/pkg/system/services/extension.go +++ b/internal/app/machined/pkg/system/services/extension.go @@ -112,6 +112,11 @@ func (svc *Extension) DependsOn(r runtime.Runtime) []string { return deps } +// Volumes implements the Service interface. +func (svc *Extension) Volumes() []string { + return nil +} + func (svc *Extension) getOCIOptions(envVars []string, mounts []specs.Mount) []oci.SpecOpts { ociOpts := []oci.SpecOpts{ oci.WithRootFSPath(filepath.Join(constants.ExtensionServiceRootfsPath, svc.Spec.Name)), diff --git a/internal/app/machined/pkg/system/services/kubelet.go b/internal/app/machined/pkg/system/services/kubelet.go index ad9a31ad5..77f307beb 100644 --- a/internal/app/machined/pkg/system/services/kubelet.go +++ b/internal/app/machined/pkg/system/services/kubelet.go @@ -105,6 +105,11 @@ func (k *Kubelet) DependsOn(runtime.Runtime) []string { return []string{"cri"} } +// Volumes implements the Service interface. +func (k *Kubelet) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (k *Kubelet) Runner(r runtime.Runtime) (runner.Runner, error) { specResource, err := safe.ReaderGet[*k8s.KubeletSpec]( diff --git a/internal/app/machined/pkg/system/services/machined.go b/internal/app/machined/pkg/system/services/machined.go index daada4dd8..fb91b83fa 100644 --- a/internal/app/machined/pkg/system/services/machined.go +++ b/internal/app/machined/pkg/system/services/machined.go @@ -227,6 +227,11 @@ func (m *Machined) DependsOn(runtime.Runtime) []string { return nil } +// Volumes implements the Service interface. +func (m *Machined) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (m *Machined) Runner(r runtime.Runtime) (runner.Runner, error) { svc := &machinedService{m.Controller} diff --git a/internal/app/machined/pkg/system/services/registryd.go b/internal/app/machined/pkg/system/services/registryd.go index fef6fbca7..ad0cd9508 100644 --- a/internal/app/machined/pkg/system/services/registryd.go +++ b/internal/app/machined/pkg/system/services/registryd.go @@ -39,6 +39,7 @@ func (r *registryD) PreFunc(context.Context, runtime.Runtime) error { retur func (r *registryD) PostFunc(runtime.Runtime, events.ServiceState) error { return nil } func (r *registryD) Condition(runtime.Runtime) conditions.Condition { return nil } func (r *registryD) DependsOn(runtime.Runtime) []string { return nil } +func (r *registryD) Volumes() []string { return nil } func (r *registryD) HealthFunc(runtime.Runtime) health.Check { return func(ctx context.Context) error { diff --git a/internal/app/machined/pkg/system/services/syslogd.go b/internal/app/machined/pkg/system/services/syslogd.go index 5621fdaf0..9c481e546 100644 --- a/internal/app/machined/pkg/system/services/syslogd.go +++ b/internal/app/machined/pkg/system/services/syslogd.go @@ -50,6 +50,11 @@ func (s *Syslogd) DependsOn(runtime.Runtime) []string { return []string{machinedServiceID} } +// Volumes implements the Service interface. +func (s *Syslogd) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (s *Syslogd) Runner(r runtime.Runtime) (runner.Runner, error) { return goroutine.NewRunner(r, syslogServiceID, syslogd.Main, runner.WithLoggingManager(r.Logging())), nil diff --git a/internal/app/machined/pkg/system/services/trustd.go b/internal/app/machined/pkg/system/services/trustd.go index 42c3a97f0..968087621 100644 --- a/internal/app/machined/pkg/system/services/trustd.go +++ b/internal/app/machined/pkg/system/services/trustd.go @@ -135,6 +135,11 @@ func (t *Trustd) DependsOn(runtime.Runtime) []string { return []string{"containerd"} } +// Volumes implements the Service interface. +func (t *Trustd) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (t *Trustd) Runner(r runtime.Runtime) (runner.Runner, error) { // Set the process arguments. diff --git a/internal/app/machined/pkg/system/services/udevd.go b/internal/app/machined/pkg/system/services/udevd.go index 9672c2a61..49abcf1dd 100644 --- a/internal/app/machined/pkg/system/services/udevd.go +++ b/internal/app/machined/pkg/system/services/udevd.go @@ -66,6 +66,11 @@ func (c *Udevd) DependsOn(runtime.Runtime) []string { return nil } +// Volumes implements the Service interface. +func (c *Udevd) Volumes() []string { + return nil +} + // Runner implements the Service interface. func (c *Udevd) Runner(r runtime.Runtime) (runner.Runner, error) { // Set the process arguments. diff --git a/internal/app/machined/pkg/system/volumes.go b/internal/app/machined/pkg/system/volumes.go new file mode 100644 index 000000000..2ec9221c5 --- /dev/null +++ b/internal/app/machined/pkg/system/volumes.go @@ -0,0 +1,94 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package system + +import ( + "context" + "fmt" + + "github.com/cosi-project/runtime/pkg/state" + + "github.com/siderolabs/talos/pkg/conditions" + "github.com/siderolabs/talos/pkg/machinery/resources/block" +) + +func (svcrunner *ServiceRunner) createVolumeMountRequest(ctx context.Context, volumeID string) (string, error) { + st := svcrunner.runtime.State().V1Alpha2().Resources() + requester := "service/" + svcrunner.id + requestID := requester + "/" + volumeID + + mountRequest := block.NewVolumeMountRequest(block.NamespaceName, requestID) + mountRequest.TypedSpec().Requester = requester + mountRequest.TypedSpec().VolumeID = volumeID + + if err := st.Create(ctx, mountRequest); err != nil { + if !state.IsConflictError(err) { + return "", fmt.Errorf("failed to create mount request: %w", err) + } + } + + return requestID, nil +} + +func (svcrunner *ServiceRunner) deleteVolumeMountRequest(ctx context.Context, requestIDs []string) error { + st := svcrunner.runtime.State().V1Alpha2().Resources() + + for _, requestID := range requestIDs { + if err := st.RemoveFinalizer(ctx, block.NewVolumeMountStatus(block.NamespaceName, requestID).Metadata(), "service"); err != nil { + if !state.IsNotFoundError(err) { + return fmt.Errorf("failed to remove finalizer from mount status %q: %w", requestID, err) + } + } + } + + for _, requestID := range requestIDs { + _, err := st.Teardown(ctx, block.NewVolumeMountRequest(block.NamespaceName, requestID).Metadata()) + if err != nil { + return fmt.Errorf("failed to teardown mount request %q: %w", requestID, err) + } + } + + for _, requestID := range requestIDs { + _, err := st.WatchFor(ctx, block.NewVolumeMountRequest(block.NamespaceName, requestID).Metadata(), state.WithFinalizerEmpty()) + if err != nil { + return fmt.Errorf("failed to wait for teardown of mount request %q: %w", requestID, err) + } + + if err = st.Destroy(ctx, block.NewVolumeMountRequest(block.NamespaceName, requestID).Metadata()); err != nil { + return fmt.Errorf("failed to destroy mount request %q: %w", requestID, err) + } + } + + return nil +} + +type volumeMountedCondition struct { + st state.State + id string +} + +func (cond *volumeMountedCondition) Wait(ctx context.Context) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + _, err := cond.st.WatchFor(ctx, block.NewVolumeMountStatus(block.NamespaceName, cond.id).Metadata(), state.WithEventTypes(state.Created, state.Updated)) + if err != nil { + return err + } + + return cond.st.AddFinalizer(ctx, block.NewVolumeMountStatus(block.NamespaceName, cond.id).Metadata(), "service") +} + +func (cond *volumeMountedCondition) String() string { + return fmt.Sprintf("volume %q to be mounted", cond.id) +} + +// WaitForVolumeToBeMounted is a service condition that will wait for the volume to be mounted. +func WaitForVolumeToBeMounted(st state.State, requestID string) conditions.Condition { + return &volumeMountedCondition{ + st: st, + id: requestID, + } +} diff --git a/internal/pkg/meta/meta.go b/internal/pkg/meta/meta.go index 003373b6d..8943e0ba4 100644 --- a/internal/pkg/meta/meta.go +++ b/internal/pkg/meta/meta.go @@ -108,6 +108,11 @@ func (meta *Meta) getPath(ctx context.Context) (string, string, error) { return "", "", err } + // add our own finalizer for the META volume to ensure it never gets removed, even in the late stages of the reboot + if err = meta.state.AddFinalizer(ctx, metaStatus.Metadata(), constants.MetaPartitionLabel); err != nil { + return "", "", err + } + if metaStatus.TypedSpec().Phase == block.VolumePhaseMissing { return "", "", os.ErrNotExist } diff --git a/pkg/conditions/all.go b/pkg/conditions/all.go index 8c029581b..3d45f1ba2 100644 --- a/pkg/conditions/all.go +++ b/pkg/conditions/all.go @@ -77,10 +77,17 @@ func (a *all) String() string { } // WaitForAll creates a condition which waits for all the conditions to be successful. +// +// If the condition is nil, it is ignored. +// WaitForAll(nil) return nil. func WaitForAll(conditions ...Condition) Condition { res := &all{} for _, c := range conditions { + if c == nil { + continue + } + if multi, ok := c.(*all); ok { // flatten lists res.conditions = append(res.conditions, multi.conditions...) diff --git a/pkg/machinery/api/resource/definitions/block/block.pb.go b/pkg/machinery/api/resource/definitions/block/block.pb.go index fcba101c2..b3b3d2be9 100644 --- a/pkg/machinery/api/resource/definitions/block/block.pb.go +++ b/pkg/machinery/api/resource/definitions/block/block.pb.go @@ -978,12 +978,12 @@ func (x *MountRequestSpec) GetReadOnly() bool { // MountSpec is the spec for volume mount. type MountSpec struct { - state protoimpl.MessageState `protogen:"open.v1"` - TargetPath string `protobuf:"bytes,1,opt,name=target_path,json=targetPath,proto3" json:"target_path,omitempty"` - SelinuxLabel string `protobuf:"bytes,2,opt,name=selinux_label,json=selinuxLabel,proto3" json:"selinux_label,omitempty"` - Options []string `protobuf:"bytes,3,rep,name=options,proto3" json:"options,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + TargetPath string `protobuf:"bytes,1,opt,name=target_path,json=targetPath,proto3" json:"target_path,omitempty"` + SelinuxLabel string `protobuf:"bytes,2,opt,name=selinux_label,json=selinuxLabel,proto3" json:"selinux_label,omitempty"` + ProjectQuotaSupport bool `protobuf:"varint,3,opt,name=project_quota_support,json=projectQuotaSupport,proto3" json:"project_quota_support,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *MountSpec) Reset() { @@ -1030,23 +1030,25 @@ func (x *MountSpec) GetSelinuxLabel() string { return "" } -func (x *MountSpec) GetOptions() []string { +func (x *MountSpec) GetProjectQuotaSupport() bool { if x != nil { - return x.Options + return x.ProjectQuotaSupport } - return nil + return false } // MountStatusSpec is the spec for MountStatus. type MountStatusSpec struct { - state protoimpl.MessageState `protogen:"open.v1"` - Spec *MountRequestSpec `protobuf:"bytes,1,opt,name=spec,proto3" json:"spec,omitempty"` - Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` - Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` - Filesystem enums.BlockFilesystemType `protobuf:"varint,4,opt,name=filesystem,proto3,enum=talos.resource.definitions.enums.BlockFilesystemType" json:"filesystem,omitempty"` - ReadOnly bool `protobuf:"varint,5,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Spec *MountRequestSpec `protobuf:"bytes,1,opt,name=spec,proto3" json:"spec,omitempty"` + Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` + Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` + Filesystem enums.BlockFilesystemType `protobuf:"varint,4,opt,name=filesystem,proto3,enum=talos.resource.definitions.enums.BlockFilesystemType" json:"filesystem,omitempty"` + ReadOnly bool `protobuf:"varint,5,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` + ProjectQuotaSupport bool `protobuf:"varint,6,opt,name=project_quota_support,json=projectQuotaSupport,proto3" json:"project_quota_support,omitempty"` + EncryptionProvider enums.BlockEncryptionProviderType `protobuf:"varint,7,opt,name=encryption_provider,json=encryptionProvider,proto3,enum=talos.resource.definitions.enums.BlockEncryptionProviderType" json:"encryption_provider,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *MountStatusSpec) Reset() { @@ -1114,6 +1116,20 @@ func (x *MountStatusSpec) GetReadOnly() bool { return false } +func (x *MountStatusSpec) GetProjectQuotaSupport() bool { + if x != nil { + return x.ProjectQuotaSupport + } + return false +} + +func (x *MountStatusSpec) GetEncryptionProvider() enums.BlockEncryptionProviderType { + if x != nil { + return x.EncryptionProvider + } + return enums.BlockEncryptionProviderType(0) +} + // PartitionSpec is the spec for volume partitioning. type PartitionSpec struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1620,24 +1636,26 @@ func (x *VolumeMountStatusSpec) GetReadOnly() bool { // VolumeStatusSpec is the spec for VolumeStatus resource. type VolumeStatusSpec struct { - state protoimpl.MessageState `protogen:"open.v1"` - Phase enums.BlockVolumePhase `protobuf:"varint,1,opt,name=phase,proto3,enum=talos.resource.definitions.enums.BlockVolumePhase" json:"phase,omitempty"` - Location string `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"` - ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` - Uuid string `protobuf:"bytes,4,opt,name=uuid,proto3" json:"uuid,omitempty"` - PartitionUuid string `protobuf:"bytes,5,opt,name=partition_uuid,json=partitionUuid,proto3" json:"partition_uuid,omitempty"` - PreFailPhase enums.BlockVolumePhase `protobuf:"varint,6,opt,name=pre_fail_phase,json=preFailPhase,proto3,enum=talos.resource.definitions.enums.BlockVolumePhase" json:"pre_fail_phase,omitempty"` - ParentLocation string `protobuf:"bytes,7,opt,name=parent_location,json=parentLocation,proto3" json:"parent_location,omitempty"` - PartitionIndex int64 `protobuf:"varint,8,opt,name=partition_index,json=partitionIndex,proto3" json:"partition_index,omitempty"` - Size uint64 `protobuf:"varint,9,opt,name=size,proto3" json:"size,omitempty"` - Filesystem enums.BlockFilesystemType `protobuf:"varint,10,opt,name=filesystem,proto3,enum=talos.resource.definitions.enums.BlockFilesystemType" json:"filesystem,omitempty"` - MountLocation string `protobuf:"bytes,11,opt,name=mount_location,json=mountLocation,proto3" json:"mount_location,omitempty"` - EncryptionProvider enums.BlockEncryptionProviderType `protobuf:"varint,12,opt,name=encryption_provider,json=encryptionProvider,proto3,enum=talos.resource.definitions.enums.BlockEncryptionProviderType" json:"encryption_provider,omitempty"` - PrettySize string `protobuf:"bytes,13,opt,name=pretty_size,json=prettySize,proto3" json:"pretty_size,omitempty"` - EncryptionFailedSyncs []string `protobuf:"bytes,14,rep,name=encryption_failed_syncs,json=encryptionFailedSyncs,proto3" json:"encryption_failed_syncs,omitempty"` - MountSpec *MountSpec `protobuf:"bytes,15,opt,name=mount_spec,json=mountSpec,proto3" json:"mount_spec,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Phase enums.BlockVolumePhase `protobuf:"varint,1,opt,name=phase,proto3,enum=talos.resource.definitions.enums.BlockVolumePhase" json:"phase,omitempty"` + Location string `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"` + ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + Uuid string `protobuf:"bytes,4,opt,name=uuid,proto3" json:"uuid,omitempty"` + PartitionUuid string `protobuf:"bytes,5,opt,name=partition_uuid,json=partitionUuid,proto3" json:"partition_uuid,omitempty"` + PreFailPhase enums.BlockVolumePhase `protobuf:"varint,6,opt,name=pre_fail_phase,json=preFailPhase,proto3,enum=talos.resource.definitions.enums.BlockVolumePhase" json:"pre_fail_phase,omitempty"` + ParentLocation string `protobuf:"bytes,7,opt,name=parent_location,json=parentLocation,proto3" json:"parent_location,omitempty"` + PartitionIndex int64 `protobuf:"varint,8,opt,name=partition_index,json=partitionIndex,proto3" json:"partition_index,omitempty"` + Size uint64 `protobuf:"varint,9,opt,name=size,proto3" json:"size,omitempty"` + Filesystem enums.BlockFilesystemType `protobuf:"varint,10,opt,name=filesystem,proto3,enum=talos.resource.definitions.enums.BlockFilesystemType" json:"filesystem,omitempty"` + MountLocation string `protobuf:"bytes,11,opt,name=mount_location,json=mountLocation,proto3" json:"mount_location,omitempty"` + EncryptionProvider enums.BlockEncryptionProviderType `protobuf:"varint,12,opt,name=encryption_provider,json=encryptionProvider,proto3,enum=talos.resource.definitions.enums.BlockEncryptionProviderType" json:"encryption_provider,omitempty"` + PrettySize string `protobuf:"bytes,13,opt,name=pretty_size,json=prettySize,proto3" json:"pretty_size,omitempty"` + EncryptionFailedSyncs []string `protobuf:"bytes,14,rep,name=encryption_failed_syncs,json=encryptionFailedSyncs,proto3" json:"encryption_failed_syncs,omitempty"` + MountSpec *MountSpec `protobuf:"bytes,15,opt,name=mount_spec,json=mountSpec,proto3" json:"mount_spec,omitempty"` + Type enums.BlockVolumeType `protobuf:"varint,16,opt,name=type,proto3,enum=talos.resource.definitions.enums.BlockVolumeType" json:"type,omitempty"` + ConfiguredEncryptionKeys []string `protobuf:"bytes,17,rep,name=configured_encryption_keys,json=configuredEncryptionKeys,proto3" json:"configured_encryption_keys,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VolumeStatusSpec) Reset() { @@ -1775,6 +1793,20 @@ func (x *VolumeStatusSpec) GetMountSpec() *MountSpec { return nil } +func (x *VolumeStatusSpec) GetType() enums.BlockVolumeType { + if x != nil { + return x.Type + } + return enums.BlockVolumeType(0) +} + +func (x *VolumeStatusSpec) GetConfiguredEncryptionKeys() []string { + if x != nil { + return x.ConfiguredEncryptionKeys + } + return nil +} + var File_resource_definitions_block_block_proto protoreflect.FileDescriptor var file_resource_definitions_block_block_proto_rawDesc = string([]byte{ @@ -1947,168 +1979,189 @@ var file_resource_definitions_block_block_proto_rawDesc = string([]byte{ 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x22, - 0x6b, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1f, 0x0a, 0x0b, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x23, 0x0a, - 0x0d, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x4c, 0x61, 0x62, - 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xfd, 0x01, 0x0a, - 0x0f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x53, 0x70, 0x65, 0x63, - 0x12, 0x46, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, - 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x70, - 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x55, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x74, - 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, - 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x8c, 0x01, 0x0a, - 0x0d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x12, 0x19, - 0x0a, 0x08, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, - 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x61, 0x78, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x72, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x04, 0x67, 0x72, 0x6f, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, - 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x1b, - 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x55, 0x75, 0x69, 0x64, 0x22, 0xae, 0x02, 0x0a, 0x10, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x70, 0x65, 0x63, - 0x12, 0x53, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x6b, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x56, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, - 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, - 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0d, - 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, - 0x04, 0x77, 0x61, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x77, 0x61, 0x76, - 0x65, 0x12, 0x59, 0x0a, 0x0f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, - 0x73, 0x70, 0x65, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x61, 0x6c, - 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0e, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x70, 0x65, 0x63, 0x22, 0x23, 0x0a, 0x0b, - 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x53, 0x70, 0x65, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x70, - 0x61, 0x74, 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, - 0x73, 0x22, 0x44, 0x0a, 0x0e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x44, 0x69, 0x73, 0x6b, 0x53, - 0x70, 0x65, 0x63, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x64, 0x65, 0x76, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x64, 0x65, 0x76, 0x50, 0x61, 0x74, 0x68, 0x22, 0x30, 0x0a, 0x18, 0x55, 0x73, 0x65, 0x72, 0x44, - 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x53, - 0x70, 0x65, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x22, 0xac, 0x03, 0x0a, 0x10, 0x56, 0x6f, - 0x6c, 0x75, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1b, - 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x74, 0x61, 0x6c, 0x6f, + 0x85, 0x01, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1f, 0x0a, + 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x23, + 0x0a, 0x0d, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x71, + 0x75, 0x6f, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, + 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x22, 0xa1, 0x03, 0x0a, 0x0f, 0x4d, 0x6f, 0x75, 0x6e, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x46, 0x0a, 0x04, 0x73, + 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x56, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, - 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0c, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x47, 0x0a, 0x07, 0x6c, 0x6f, - 0x63, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x61, - 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, - 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4c, - 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x70, 0x65, 0x63, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x6f, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, - 0x05, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x0a, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x61, 0x6c, - 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x45, 0x6e, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0a, 0x65, 0x6e, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x70, 0x0a, 0x16, 0x56, 0x6f, 0x6c, 0x75, - 0x6d, 0x65, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x70, - 0x65, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x49, 0x64, 0x12, - 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x1b, 0x0a, - 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x87, 0x01, 0x0a, 0x15, 0x56, - 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x53, 0x70, 0x65, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x49, - 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, - 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, - 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, - 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0xab, 0x06, 0x0a, 0x10, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x48, 0x0a, 0x05, 0x70, 0x68, 0x61, - 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x05, 0x70, 0x68, - 0x61, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x75, 0x69, 0x64, 0x12, - 0x58, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x5f, 0x70, 0x68, 0x61, 0x73, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4d, 0x6f, 0x75, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, + 0x70, 0x65, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x55, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x65, - 0x46, 0x61, 0x69, 0x6c, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, - 0x55, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6c, 0x65, - 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, - 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6e, 0x0a, - 0x13, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3d, 0x2e, 0x74, 0x61, 0x6c, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, + 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, + 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x5f, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x51, + 0x75, 0x6f, 0x74, 0x61, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x6e, 0x0a, 0x13, 0x65, + 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3d, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x12, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x22, 0x8c, 0x01, 0x0a, 0x0d, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x12, 0x19, 0x0a, + 0x08, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x07, 0x6d, 0x69, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x53, + 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x72, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x04, 0x67, 0x72, 0x6f, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x1b, 0x0a, + 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x55, 0x75, 0x69, 0x64, 0x22, 0xae, 0x02, 0x0a, 0x10, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x70, 0x65, 0x63, 0x12, + 0x53, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x6b, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x12, 0x56, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, + 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, + 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0d, 0x70, + 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, + 0x77, 0x61, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x77, 0x61, 0x76, 0x65, + 0x12, 0x59, 0x0a, 0x0f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x73, + 0x70, 0x65, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x61, 0x6c, 0x6f, + 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0e, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x70, 0x65, 0x63, 0x22, 0x23, 0x0a, 0x0b, 0x53, + 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x53, 0x70, 0x65, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, + 0x74, 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, + 0x22, 0x44, 0x0a, 0x0e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x44, 0x69, 0x73, 0x6b, 0x53, 0x70, + 0x65, 0x63, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x64, + 0x65, 0x76, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, + 0x65, 0x76, 0x50, 0x61, 0x74, 0x68, 0x22, 0x30, 0x0a, 0x18, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, + 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x53, 0x70, + 0x65, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x22, 0xac, 0x03, 0x0a, 0x10, 0x56, 0x6f, 0x6c, + 0x75, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1b, 0x0a, + 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x56, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, + 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0c, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x47, 0x0a, 0x07, 0x6c, 0x6f, 0x63, + 0x61, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x12, 0x65, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, - 0x0b, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x36, - 0x0a, 0x17, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x15, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x53, 0x79, 0x6e, 0x63, 0x73, 0x12, 0x4a, 0x0a, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, - 0x73, 0x70, 0x65, 0x63, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x74, 0x61, 0x6c, - 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4d, 0x6f, - 0x75, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x70, - 0x65, 0x63, 0x42, 0x74, 0x0a, 0x28, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, - 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5a, 0x48, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, - 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4c, 0x6f, + 0x63, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x70, 0x65, 0x63, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x74, + 0x6f, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x05, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x0a, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x61, 0x6c, 0x6f, + 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x45, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0a, 0x65, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x70, 0x0a, 0x16, 0x56, 0x6f, 0x6c, 0x75, 0x6d, + 0x65, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x70, 0x65, + 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, + 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x87, 0x01, 0x0a, 0x15, 0x56, 0x6f, + 0x6c, 0x75, 0x6d, 0x65, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x53, + 0x70, 0x65, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x49, 0x64, + 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x16, + 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, + 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, + 0x6e, 0x6c, 0x79, 0x22, 0xb0, 0x07, 0x0a, 0x10, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x48, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x05, 0x70, 0x68, 0x61, + 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, + 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x74, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x75, 0x69, 0x64, 0x12, 0x58, + 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x46, + 0x61, 0x69, 0x6c, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x74, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x55, + 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6e, 0x0a, 0x13, + 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3d, 0x2e, 0x74, 0x61, 0x6c, 0x6f, + 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x12, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, + 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x36, 0x0a, + 0x17, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, + 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x53, 0x79, 0x6e, 0x63, 0x73, 0x12, 0x4a, 0x0a, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x73, + 0x70, 0x65, 0x63, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x74, 0x61, 0x6c, 0x6f, + 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4d, 0x6f, 0x75, + 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x70, 0x65, + 0x63, 0x12, 0x45, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x31, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6e, 0x75, + 0x6d, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x1a, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x42, 0x74, 0x0a, 0x28, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x61, + 0x6c, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x5a, 0x48, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, + 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, + 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -2163,24 +2216,26 @@ var file_resource_definitions_block_block_proto_depIdxs = []int32{ 22, // 5: talos.resource.definitions.block.LocatorSpec.match:type_name -> google.api.expr.v1alpha1.CheckedExpr 10, // 6: talos.resource.definitions.block.MountStatusSpec.spec:type_name -> talos.resource.definitions.block.MountRequestSpec 25, // 7: talos.resource.definitions.block.MountStatusSpec.filesystem:type_name -> talos.resource.definitions.enums.BlockFilesystemType - 4, // 8: talos.resource.definitions.block.ProvisioningSpec.disk_selector:type_name -> talos.resource.definitions.block.DiskSelector - 13, // 9: talos.resource.definitions.block.ProvisioningSpec.partition_spec:type_name -> talos.resource.definitions.block.PartitionSpec - 8, // 10: talos.resource.definitions.block.ProvisioningSpec.filesystem_spec:type_name -> talos.resource.definitions.block.FilesystemSpec - 26, // 11: talos.resource.definitions.block.VolumeConfigSpec.type:type_name -> talos.resource.definitions.enums.BlockVolumeType - 14, // 12: talos.resource.definitions.block.VolumeConfigSpec.provisioning:type_name -> talos.resource.definitions.block.ProvisioningSpec - 9, // 13: talos.resource.definitions.block.VolumeConfigSpec.locator:type_name -> talos.resource.definitions.block.LocatorSpec - 11, // 14: talos.resource.definitions.block.VolumeConfigSpec.mount:type_name -> talos.resource.definitions.block.MountSpec - 7, // 15: talos.resource.definitions.block.VolumeConfigSpec.encryption:type_name -> talos.resource.definitions.block.EncryptionSpec - 27, // 16: talos.resource.definitions.block.VolumeStatusSpec.phase:type_name -> talos.resource.definitions.enums.BlockVolumePhase - 27, // 17: talos.resource.definitions.block.VolumeStatusSpec.pre_fail_phase:type_name -> talos.resource.definitions.enums.BlockVolumePhase - 25, // 18: talos.resource.definitions.block.VolumeStatusSpec.filesystem:type_name -> talos.resource.definitions.enums.BlockFilesystemType - 24, // 19: talos.resource.definitions.block.VolumeStatusSpec.encryption_provider:type_name -> talos.resource.definitions.enums.BlockEncryptionProviderType - 11, // 20: talos.resource.definitions.block.VolumeStatusSpec.mount_spec:type_name -> talos.resource.definitions.block.MountSpec - 21, // [21:21] is the sub-list for method output_type - 21, // [21:21] is the sub-list for method input_type - 21, // [21:21] is the sub-list for extension type_name - 21, // [21:21] is the sub-list for extension extendee - 0, // [0:21] is the sub-list for field type_name + 24, // 8: talos.resource.definitions.block.MountStatusSpec.encryption_provider:type_name -> talos.resource.definitions.enums.BlockEncryptionProviderType + 4, // 9: talos.resource.definitions.block.ProvisioningSpec.disk_selector:type_name -> talos.resource.definitions.block.DiskSelector + 13, // 10: talos.resource.definitions.block.ProvisioningSpec.partition_spec:type_name -> talos.resource.definitions.block.PartitionSpec + 8, // 11: talos.resource.definitions.block.ProvisioningSpec.filesystem_spec:type_name -> talos.resource.definitions.block.FilesystemSpec + 26, // 12: talos.resource.definitions.block.VolumeConfigSpec.type:type_name -> talos.resource.definitions.enums.BlockVolumeType + 14, // 13: talos.resource.definitions.block.VolumeConfigSpec.provisioning:type_name -> talos.resource.definitions.block.ProvisioningSpec + 9, // 14: talos.resource.definitions.block.VolumeConfigSpec.locator:type_name -> talos.resource.definitions.block.LocatorSpec + 11, // 15: talos.resource.definitions.block.VolumeConfigSpec.mount:type_name -> talos.resource.definitions.block.MountSpec + 7, // 16: talos.resource.definitions.block.VolumeConfigSpec.encryption:type_name -> talos.resource.definitions.block.EncryptionSpec + 27, // 17: talos.resource.definitions.block.VolumeStatusSpec.phase:type_name -> talos.resource.definitions.enums.BlockVolumePhase + 27, // 18: talos.resource.definitions.block.VolumeStatusSpec.pre_fail_phase:type_name -> talos.resource.definitions.enums.BlockVolumePhase + 25, // 19: talos.resource.definitions.block.VolumeStatusSpec.filesystem:type_name -> talos.resource.definitions.enums.BlockFilesystemType + 24, // 20: talos.resource.definitions.block.VolumeStatusSpec.encryption_provider:type_name -> talos.resource.definitions.enums.BlockEncryptionProviderType + 11, // 21: talos.resource.definitions.block.VolumeStatusSpec.mount_spec:type_name -> talos.resource.definitions.block.MountSpec + 26, // 22: talos.resource.definitions.block.VolumeStatusSpec.type:type_name -> talos.resource.definitions.enums.BlockVolumeType + 23, // [23:23] is the sub-list for method output_type + 23, // [23:23] is the sub-list for method input_type + 23, // [23:23] is the sub-list for extension type_name + 23, // [23:23] is the sub-list for extension extendee + 0, // [0:23] is the sub-list for field type_name } func init() { file_resource_definitions_block_block_proto_init() } diff --git a/pkg/machinery/api/resource/definitions/block/block_vtproto.pb.go b/pkg/machinery/api/resource/definitions/block/block_vtproto.pb.go index f5733d158..2bbd05a1f 100644 --- a/pkg/machinery/api/resource/definitions/block/block_vtproto.pb.go +++ b/pkg/machinery/api/resource/definitions/block/block_vtproto.pb.go @@ -924,14 +924,15 @@ func (m *MountSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if len(m.Options) > 0 { - for iNdEx := len(m.Options) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Options[iNdEx]) - copy(dAtA[i:], m.Options[iNdEx]) - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Options[iNdEx]))) - i-- - dAtA[i] = 0x1a + if m.ProjectQuotaSupport { + i-- + if m.ProjectQuotaSupport { + dAtA[i] = 1 + } else { + dAtA[i] = 0 } + i-- + dAtA[i] = 0x18 } if len(m.SelinuxLabel) > 0 { i -= len(m.SelinuxLabel) @@ -980,6 +981,21 @@ func (m *MountStatusSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.EncryptionProvider != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.EncryptionProvider)) + i-- + dAtA[i] = 0x38 + } + if m.ProjectQuotaSupport { + i-- + if m.ProjectQuotaSupport { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } if m.ReadOnly { i-- if m.ReadOnly { @@ -1525,6 +1541,24 @@ func (m *VolumeStatusSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.ConfiguredEncryptionKeys) > 0 { + for iNdEx := len(m.ConfiguredEncryptionKeys) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ConfiguredEncryptionKeys[iNdEx]) + copy(dAtA[i:], m.ConfiguredEncryptionKeys[iNdEx]) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.ConfiguredEncryptionKeys[iNdEx]))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + } + if m.Type != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x80 + } if m.MountSpec != nil { size, err := m.MountSpec.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -2021,11 +2055,8 @@ func (m *MountSpec) SizeVT() (n int) { if l > 0 { n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } - if len(m.Options) > 0 { - for _, s := range m.Options { - l = len(s) - n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) - } + if m.ProjectQuotaSupport { + n += 2 } n += len(m.unknownFields) return n @@ -2055,6 +2086,12 @@ func (m *MountStatusSpec) SizeVT() (n int) { if m.ReadOnly { n += 2 } + if m.ProjectQuotaSupport { + n += 2 + } + if m.EncryptionProvider != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.EncryptionProvider)) + } n += len(m.unknownFields) return n } @@ -2299,6 +2336,15 @@ func (m *VolumeStatusSpec) SizeVT() (n int) { l = m.MountSpec.SizeVT() n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + if m.Type != 0 { + n += 2 + protohelpers.SizeOfVarint(uint64(m.Type)) + } + if len(m.ConfiguredEncryptionKeys) > 0 { + for _, s := range m.ConfiguredEncryptionKeys { + l = len(s) + n += 2 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } n += len(m.unknownFields) return n } @@ -4816,10 +4862,10 @@ func (m *MountSpec) UnmarshalVT(dAtA []byte) error { m.SelinuxLabel = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProjectQuotaSupport", wireType) } - var stringLen uint64 + var v int for shift := uint(0); ; shift += 7 { if shift >= 64 { return protohelpers.ErrIntOverflow @@ -4829,24 +4875,12 @@ func (m *MountSpec) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + v |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protohelpers.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return protohelpers.ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Options = append(m.Options, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex + m.ProjectQuotaSupport = bool(v != 0) default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -5037,6 +5071,45 @@ func (m *MountStatusSpec) UnmarshalVT(dAtA []byte) error { } } m.ReadOnly = bool(v != 0) + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProjectQuotaSupport", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.ProjectQuotaSupport = bool(v != 0) + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EncryptionProvider", wireType) + } + m.EncryptionProvider = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.EncryptionProvider |= enums.BlockEncryptionProviderType(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -6662,6 +6735,57 @@ func (m *VolumeStatusSpec) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 16: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= enums.BlockVolumeType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConfiguredEncryptionKeys", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConfiguredEncryptionKeys = append(m.ConfiguredEncryptionKeys, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/pkg/machinery/go.mod b/pkg/machinery/go.mod index ba44df197..d353766eb 100644 --- a/pkg/machinery/go.mod +++ b/pkg/machinery/go.mod @@ -14,7 +14,7 @@ replace ( require ( github.com/blang/semver/v4 v4.0.0 github.com/containerd/go-cni v1.1.12 - github.com/cosi-project/runtime v0.10.0 + github.com/cosi-project/runtime v0.10.1 github.com/dustin/go-humanize v1.0.1 github.com/emicklei/dot v1.7.0 github.com/evanphx/json-patch v5.9.11+incompatible @@ -56,8 +56,8 @@ require ( github.com/containernetworking/cni v1.2.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/gertd/go-pluralize v0.2.1 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/josharian/native v1.1.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect diff --git a/pkg/machinery/go.sum b/pkg/machinery/go.sum index 45e0dbe4b..2daa5f369 100644 --- a/pkg/machinery/go.sum +++ b/pkg/machinery/go.sum @@ -24,8 +24,8 @@ github.com/containerd/go-cni v1.1.12 h1:wm/5VD/i255hjM4uIZjBRiEQ7y98W9ACy/mHeLi4 github.com/containerd/go-cni v1.1.12/go.mod h1:+jaqRBdtW5faJxj2Qwg1Of7GsV66xcvnCx4mSJtUlxU= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= -github.com/cosi-project/runtime v0.10.0 h1:8CvXq5TtFIJY4/PZQh2iCgZMs8hxOLzoU64abs6k5dc= -github.com/cosi-project/runtime v0.10.0/go.mod h1:ZQGhCKF7YD42wFlZdw5y9RVIjlbviIyn0cYnmLdQ3Qs= +github.com/cosi-project/runtime v0.10.1 h1:s3LWW3UZgORKSINhNFd1G0RZevAatQ01+70cIWdKK7c= +github.com/cosi-project/runtime v0.10.1/go.mod h1:AdQvVoG6kfhGwWEqsFxndynrp1jr8KNoYj75dHJCxcE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -52,14 +52,14 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/cel-go v0.24.1 h1:jsBCtxG8mM5wiUJDSGUqU0K7Mtr3w7Eyv00rw4DiZxI= github.com/google/cel-go v0.24.1/go.mod h1:Hdf9TqOaTNSFQA1ybQaRqATVoK7m/zcf7IMhGXP5zI8= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.2 h1:VpMASoqIPXLWWdkkbTA9ZyoP8J9Jw0M7S82qEhkALFs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.2/go.mod h1:FYBptsOc6KxMvX44fK7+t/bQcDcDI4UGibbAuuAnRu4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/pkg/machinery/resources/block/block.go b/pkg/machinery/resources/block/block.go index 7e324a086..5780b3224 100644 --- a/pkg/machinery/resources/block/block.go +++ b/pkg/machinery/resources/block/block.go @@ -13,7 +13,9 @@ import ( "github.com/cosi-project/runtime/pkg/resource" "github.com/cosi-project/runtime/pkg/safe" "github.com/cosi-project/runtime/pkg/state" + "github.com/siderolabs/gen/maps" + "github.com/siderolabs/talos/pkg/machinery/constants" "github.com/siderolabs/talos/pkg/machinery/resources/v1alpha1" ) @@ -65,3 +67,40 @@ func GetSystemDisk(ctx context.Context, st state.State) (*SystemDiskSpec, error) return systemDisk.TypedSpec(), nil } + +// GetSystemDiskPaths returns the path(s) of system disk and STATE/EPHEMERAL partitions. +// +// This is a legacy method to map old concept of system disk wipe into new volume subsystem. +func GetSystemDiskPaths(ctx context.Context, st state.State) ([]string, error) { + systemDisks := map[string]struct{}{} + + // fetch system disk (where Talos is installed) + systemDisk, err := GetSystemDisk(ctx, st) + if err != nil { + return nil, err + } + + if systemDisk != nil { + systemDisks[systemDisk.DevPath] = struct{}{} + } + + // fetch additional system volumes (which might be on the same or other disks) + for _, volumeID := range []string{constants.StatePartitionLabel, constants.EphemeralPartitionLabel} { + volumeStatus, err := safe.ReaderGetByID[*VolumeStatus](ctx, st, volumeID) + if err != nil { + if state.IsNotFoundError(err) { + continue + } + + return nil, err + } + + if volumeStatus.TypedSpec().ParentLocation != "" { + systemDisks[volumeStatus.TypedSpec().ParentLocation] = struct{}{} + } else if volumeStatus.TypedSpec().Location != "" { + systemDisks[volumeStatus.TypedSpec().Location] = struct{}{} + } + } + + return maps.Keys(systemDisks), nil +} diff --git a/pkg/machinery/resources/block/deep_copy.generated.go b/pkg/machinery/resources/block/deep_copy.generated.go index 23fa02562..0f03ef32f 100644 --- a/pkg/machinery/resources/block/deep_copy.generated.go +++ b/pkg/machinery/resources/block/deep_copy.generated.go @@ -108,10 +108,6 @@ func (o VolumeConfigSpec) DeepCopy() VolumeConfigSpec { cp.Encryption.PerfOptions = make([]string, len(o.Encryption.PerfOptions)) copy(cp.Encryption.PerfOptions, o.Encryption.PerfOptions) } - if o.Mount.Options != nil { - cp.Mount.Options = make([]string, len(o.Mount.Options)) - copy(cp.Mount.Options, o.Mount.Options) - } return cp } @@ -140,9 +136,9 @@ func (o VolumeStatusSpec) DeepCopy() VolumeStatusSpec { cp.EncryptionFailedSyncs = make([]string, len(o.EncryptionFailedSyncs)) copy(cp.EncryptionFailedSyncs, o.EncryptionFailedSyncs) } - if o.MountSpec.Options != nil { - cp.MountSpec.Options = make([]string, len(o.MountSpec.Options)) - copy(cp.MountSpec.Options, o.MountSpec.Options) + if o.ConfiguredEncryptionKeys != nil { + cp.ConfiguredEncryptionKeys = make([]string, len(o.ConfiguredEncryptionKeys)) + copy(cp.ConfiguredEncryptionKeys, o.ConfiguredEncryptionKeys) } return cp } diff --git a/pkg/machinery/resources/block/mount_request.go b/pkg/machinery/resources/block/mount_request.go index 441121c71..2b604898c 100644 --- a/pkg/machinery/resources/block/mount_request.go +++ b/pkg/machinery/resources/block/mount_request.go @@ -23,13 +23,13 @@ type MountRequest = typed.Resource[MountRequestSpec, MountRequestExtension] // //gotagsrewrite:gen type MountRequestSpec struct { - VolumeID string `yaml:"volume_id" protobuf:"1"` + VolumeID string `yaml:"volumeID" protobuf:"1"` - ParentMountID string `yaml:"parent_id" protobuf:"2"` - ReadOnly bool `yaml:"read_only" protobuf:"5"` + ParentMountID string `yaml:"parentID" protobuf:"2"` + ReadOnly bool `yaml:"readOnly" protobuf:"5"` Requesters []string `yaml:"requesters" protobuf:"3"` - RequesterIDs []string `yaml:"requester_ids" protobuf:"4"` + RequesterIDs []string `yaml:"requesterIDs" protobuf:"4"` } // NewMountRequest initializes a MountRequest resource. @@ -51,20 +51,16 @@ func (MountRequestExtension) ResourceDefinition() meta.ResourceDefinitionSpec { DefaultNamespace: NamespaceName, PrintColumns: []meta.PrintColumn{ { - Name: "Source", - JSONPath: `{.source}`, - }, - { - Name: "Target", - JSONPath: `{.target}`, - }, - { - Name: "FSType", - JSONPath: `{.fs_type}`, + Name: "Volume", + JSONPath: `{.volumeID}`, }, { Name: "Parent", - JSONPath: `{.parent_id}`, + JSONPath: `{.ParentID}`, + }, + { + Name: "Requesters", + JSONPath: `{.requesters}`, }, }, } diff --git a/pkg/machinery/resources/block/mount_status.go b/pkg/machinery/resources/block/mount_status.go index 966edac0d..3e90392e0 100644 --- a/pkg/machinery/resources/block/mount_status.go +++ b/pkg/machinery/resources/block/mount_status.go @@ -23,12 +23,14 @@ type MountStatus = typed.Resource[MountStatusSpec, MountStatusExtension] // //gotagsrewrite:gen type MountStatusSpec struct { - Spec MountRequestSpec `yaml:"spec" protobuf:"1"` - Source string `yaml:"source" protobuf:"3"` - Target string `yaml:"target" protobuf:"2"` - Filesystem FilesystemType `yaml:"filesystem" protobuf:"4"` + Spec MountRequestSpec `yaml:"spec" protobuf:"1"` + Source string `yaml:"source" protobuf:"3"` + Target string `yaml:"target" protobuf:"2"` + Filesystem FilesystemType `yaml:"filesystem" protobuf:"4"` + EncryptionProvider EncryptionProviderType `yaml:"encryptionProvider,omitempty" protobuf:"7"` - ReadOnly bool `yaml:"read_only" protobuf:"5"` + ReadOnly bool `yaml:"readOnly" protobuf:"5"` + ProjectQuotaSupport bool `yaml:"projectQuotaSupport" protobuf:"6"` } // NewMountStatus initializes a MountStatus resource. @@ -62,8 +64,8 @@ func (MountStatusExtension) ResourceDefinition() meta.ResourceDefinitionSpec { JSONPath: `{.filesystem}`, }, { - Name: "Parent", - JSONPath: `{.spec.mount_parent_id}`, + Name: "Volume", + JSONPath: `{.spec.volumeID}`, }, }, } diff --git a/pkg/machinery/resources/block/volume_config.go b/pkg/machinery/resources/block/volume_config.go index 2dc780412..d969681fa 100644 --- a/pkg/machinery/resources/block/volume_config.go +++ b/pkg/machinery/resources/block/volume_config.go @@ -150,8 +150,8 @@ type MountSpec struct { TargetPath string `yaml:"targetPath" protobuf:"1"` // SELinux label for the volume. SelinuxLabel string `yaml:"selinuxLabel" protobuf:"2"` - // Mount options for the volume. - Options []string `yaml:"options,omitempty" protobuf:"3"` + // Enable project quota (xfs) for the volume. + ProjectQuotaSupport bool `yaml:"projectQuotaSupport" protobuf:"3"` } // NewVolumeConfig initializes a BlockVolumeConfig resource. diff --git a/pkg/machinery/resources/block/volume_mount_request.go b/pkg/machinery/resources/block/volume_mount_request.go index db6769ffe..f2407d9f8 100644 --- a/pkg/machinery/resources/block/volume_mount_request.go +++ b/pkg/machinery/resources/block/volume_mount_request.go @@ -23,9 +23,9 @@ type VolumeMountRequest = typed.Resource[VolumeMountRequestSpec, VolumeMountRequ // //gotagsrewrite:gen type VolumeMountRequestSpec struct { - VolumeID string `yaml:"volume_id" protobuf:"1"` + VolumeID string `yaml:"volumeID" protobuf:"1"` - ReadOnly bool `yaml:"read_only" protobuf:"3"` + ReadOnly bool `yaml:"readOnly" protobuf:"3"` Requester string `yaml:"requester" protobuf:"2"` } @@ -50,7 +50,7 @@ func (VolumeMountRequestExtension) ResourceDefinition() meta.ResourceDefinitionS PrintColumns: []meta.PrintColumn{ { Name: "Volume ID", - JSONPath: `{.volume_id}`, + JSONPath: `{.volumeID}`, }, { Name: "Requester", diff --git a/pkg/machinery/resources/block/volume_mount_status.go b/pkg/machinery/resources/block/volume_mount_status.go index 213668ec1..f9057b745 100644 --- a/pkg/machinery/resources/block/volume_mount_status.go +++ b/pkg/machinery/resources/block/volume_mount_status.go @@ -23,11 +23,11 @@ type VolumeMountStatus = typed.Resource[VolumeMountStatusSpec, VolumeMountStatus // //gotagsrewrite:gen type VolumeMountStatusSpec struct { - VolumeID string `yaml:"volume_id" protobuf:"1"` + VolumeID string `yaml:"volumeID" protobuf:"1"` Requester string `yaml:"requester" protobuf:"2"` Target string `yaml:"target" protobuf:"3"` - ReadOnly bool `yaml:"read_only" protobuf:"4"` + ReadOnly bool `yaml:"readOnly" protobuf:"4"` } // NewVolumeMountStatus initializes a VolumeMountStatus resource. @@ -50,7 +50,7 @@ func (VolumeMountStatusExtension) ResourceDefinition() meta.ResourceDefinitionSp PrintColumns: []meta.PrintColumn{ { Name: "Volume ID", - JSONPath: `{.volume_id}`, + JSONPath: `{.volumeID}`, }, { Name: "Requester", diff --git a/pkg/machinery/resources/block/volume_status.go b/pkg/machinery/resources/block/volume_status.go index b344a5a3b..04c568ae6 100644 --- a/pkg/machinery/resources/block/volume_status.go +++ b/pkg/machinery/resources/block/volume_status.go @@ -27,6 +27,8 @@ type VolumeStatusSpec struct { Phase VolumePhase `yaml:"phase" protobuf:"1"` PreFailPhase VolumePhase `yaml:"preFailPhase,omitempty" protobuf:"6"` + Type VolumeType `yaml:"type" protobuf:"16"` + // Location is the path to the block device (raw). Location string `yaml:"location,omitempty" protobuf:"2"` // MountLocation is the location to be mounted, might be different from location. @@ -44,9 +46,12 @@ type VolumeStatusSpec struct { // Filesystem is the filesystem type. Filesystem FilesystemType `yaml:"filesystem,omitempty" protobuf:"10"` - // EncryptionProvider is the provider of the encryption. - EncryptionProvider EncryptionProviderType `yaml:"encryptionProvider,omitempty" protobuf:"12"` - EncryptionFailedSyncs []string `yaml:"encryptionFailedSyncs,omitempty" protobuf:"14"` + // EncryptionProvider is the provider of the encryption which was used to unlock the volume. + EncryptionProvider EncryptionProviderType `yaml:"encryptionProvider,omitempty" protobuf:"12"` + // EncryptionFailedSyncs is the list of failed syncs for the volume (per key/provider)/ + EncryptionFailedSyncs []string `yaml:"encryptionFailedSyncs,omitempty" protobuf:"14"` + // ConfiguredEncryptionKeys is the list of configured encryption keys for the volume. + ConfiguredEncryptionKeys []string `yaml:"configuredEncryptionKeys,omitempty" protobuf:"17"` // MountSpec is the mount specification. MountSpec MountSpec `yaml:"mountSpec,omitempty" protobuf:"15"` @@ -78,6 +83,10 @@ func (VolumeStatusExtension) ResourceDefinition() meta.ResourceDefinitionSpec { Aliases: []resource.Type{}, DefaultNamespace: NamespaceName, PrintColumns: []meta.PrintColumn{ + { + Name: "Type", + JSONPath: `{.type}`, + }, { Name: "Phase", JSONPath: `{.phase}`, diff --git a/website/content/v1.10/reference/api.md b/website/content/v1.10/reference/api.md index f6c03d268..038438f07 100644 --- a/website/content/v1.10/reference/api.md +++ b/website/content/v1.10/reference/api.md @@ -1055,7 +1055,7 @@ MountSpec is the spec for volume mount. | ----- | ---- | ----- | ----------- | | target_path | [string](#string) | | | | selinux_label | [string](#string) | | | -| options | [string](#string) | repeated | | +| project_quota_support | [bool](#bool) | | | @@ -1075,6 +1075,8 @@ MountStatusSpec is the spec for MountStatus. | source | [string](#string) | | | | filesystem | [talos.resource.definitions.enums.BlockFilesystemType](#talos.resource.definitions.enums.BlockFilesystemType) | | | | read_only | [bool](#bool) | | | +| project_quota_support | [bool](#bool) | | | +| encryption_provider | [talos.resource.definitions.enums.BlockEncryptionProviderType](#talos.resource.definitions.enums.BlockEncryptionProviderType) | | | @@ -1242,6 +1244,8 @@ VolumeStatusSpec is the spec for VolumeStatus resource. | pretty_size | [string](#string) | | | | encryption_failed_syncs | [string](#string) | repeated | | | mount_spec | [MountSpec](#talos.resource.definitions.block.MountSpec) | | | +| type | [talos.resource.definitions.enums.BlockVolumeType](#talos.resource.definitions.enums.BlockVolumeType) | | | +| configured_encryption_keys | [string](#string) | repeated | |