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 | |