mirror of
https://github.com/siderolabs/talos.git
synced 2026-05-05 12:26:21 +02:00
feat: implement block device wipe
Fixes #9731 The wipe doesn't require a reboot, but it requires the blockdevice not to be used as a volume. Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
parent
6fb518ae57
commit
cc768037f8
@ -11,6 +11,12 @@ import "google/protobuf/empty.proto";
|
||||
// StorageService represents the storage service.
|
||||
service StorageService {
|
||||
rpc Disks(google.protobuf.Empty) returns (DisksResponse);
|
||||
// BlockDeviceWipe performs a wipe of the blockdevice (partition or disk).
|
||||
//
|
||||
// The method doesn't require a reboot, and it can only wipe blockdevices which are not
|
||||
// being used as volumes at the moment.
|
||||
// Wiping of volumes requires a different API.
|
||||
rpc BlockDeviceWipe(BlockDeviceWipeRequest) returns (BlockDeviceWipeResponse);
|
||||
}
|
||||
|
||||
// Disk represents a disk.
|
||||
@ -60,3 +66,39 @@ message Disks {
|
||||
message DisksResponse {
|
||||
repeated Disks messages = 1;
|
||||
}
|
||||
|
||||
// rpc BlockDeviceWipe
|
||||
|
||||
message BlockDeviceWipeRequest {
|
||||
repeated BlockDeviceWipeDescriptor devices = 1;
|
||||
}
|
||||
|
||||
// BlockDeviceWipeDescriptor represents a single block device to be wiped.
|
||||
//
|
||||
// The device can be either a full disk (e.g. vda) or a partition (vda5).
|
||||
// The device should not be used in any of active volumes.
|
||||
// The device should not be used as a secondary (e.g. part of LVM).
|
||||
message BlockDeviceWipeDescriptor {
|
||||
enum Method {
|
||||
// Fast wipe - wipe only filesystem signatures.
|
||||
FAST = 0;
|
||||
// Zeroes wipe - wipe by overwriting with zeroes (might be slow depending on the disk size and available hardware features).
|
||||
ZEROES = 1;
|
||||
}
|
||||
// Device name to wipe (e.g. sda or sda5).
|
||||
//
|
||||
// The name should be submitted without `/dev/` prefix.
|
||||
string device = 1;
|
||||
// Wipe method to use.
|
||||
Method method = 2;
|
||||
// Skip the volume in use check.
|
||||
bool skip_volume_check = 3;
|
||||
}
|
||||
|
||||
message BlockDeviceWipeResponse {
|
||||
repeated BlockDeviceWipe messages = 1;
|
||||
}
|
||||
|
||||
message BlockDeviceWipe {
|
||||
common.Metadata metadata = 1;
|
||||
}
|
||||
|
||||
@ -5,138 +5,21 @@
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"errors"
|
||||
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/cli"
|
||||
"github.com/siderolabs/talos/pkg/machinery/client"
|
||||
)
|
||||
|
||||
var disksCmdFlags struct {
|
||||
insecure bool
|
||||
}
|
||||
|
||||
var disksCmd = &cobra.Command{
|
||||
Use: "disks",
|
||||
Short: "Get the list of disks from /sys/block on the machine",
|
||||
Long: ``,
|
||||
Use: "disks",
|
||||
Short: "Get the list of disks from /sys/block on the machine",
|
||||
Long: ``,
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if disksCmdFlags.insecure {
|
||||
return WithClientMaintenance(nil, printDisks)
|
||||
}
|
||||
|
||||
return WithClient(printDisks)
|
||||
return errors.New("`talosctl disks` is deprecated, please use `talosctl get disks`, `talosctl get systemdisk`, `talosctl get discoveredvolumes` instead")
|
||||
},
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func printDisks(ctx context.Context, c *client.Client) error {
|
||||
response, err := c.Disks(ctx)
|
||||
if err != nil {
|
||||
if response == nil {
|
||||
return fmt.Errorf("error getting disks: %w", err)
|
||||
}
|
||||
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
node := ""
|
||||
|
||||
labels := strings.Join(
|
||||
[]string{
|
||||
"DEV",
|
||||
"MODEL",
|
||||
"SERIAL",
|
||||
"TYPE",
|
||||
"UUID",
|
||||
"WWID",
|
||||
"MODALIAS",
|
||||
"NAME",
|
||||
"SIZE",
|
||||
"BUS_PATH",
|
||||
"SUBSYSTEM",
|
||||
"READ_ONLY",
|
||||
"SYSTEM_DISK",
|
||||
}, "\t")
|
||||
|
||||
getWithPlaceholder := func(in string) string {
|
||||
if in == "" {
|
||||
return "-"
|
||||
}
|
||||
|
||||
return in
|
||||
}
|
||||
|
||||
for i, message := range response.Messages {
|
||||
if message.Metadata != nil && message.Metadata.Hostname != "" {
|
||||
node = message.Metadata.Hostname
|
||||
}
|
||||
|
||||
if len(message.Disks) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for j, disk := range message.Disks {
|
||||
if i == 0 && j == 0 {
|
||||
if node != "" {
|
||||
fmt.Fprintln(w, "NODE\t"+labels)
|
||||
} else {
|
||||
fmt.Fprintln(w, labels)
|
||||
}
|
||||
}
|
||||
|
||||
var args []any
|
||||
|
||||
if node != "" {
|
||||
args = append(args, node)
|
||||
}
|
||||
|
||||
isReadonly := ""
|
||||
|
||||
if disk.Readonly {
|
||||
isReadonly = "*"
|
||||
}
|
||||
|
||||
isSystemDisk := ""
|
||||
|
||||
if disk.SystemDisk {
|
||||
isSystemDisk = "*"
|
||||
}
|
||||
|
||||
args = append(args, []any{
|
||||
getWithPlaceholder(disk.DeviceName),
|
||||
getWithPlaceholder(disk.Model),
|
||||
getWithPlaceholder(disk.Serial),
|
||||
disk.Type.String(),
|
||||
getWithPlaceholder(disk.Uuid),
|
||||
getWithPlaceholder(disk.Wwid),
|
||||
getWithPlaceholder(disk.Modalias),
|
||||
getWithPlaceholder(disk.Name),
|
||||
humanize.Bytes(disk.Size),
|
||||
getWithPlaceholder(disk.BusPath),
|
||||
getWithPlaceholder(disk.Subsystem),
|
||||
isReadonly,
|
||||
isSystemDisk,
|
||||
}...)
|
||||
|
||||
pattern := strings.Repeat("%s\t", len(args))
|
||||
pattern = strings.TrimSpace(pattern) + "\n"
|
||||
|
||||
fmt.Fprintf(w, pattern, args...)
|
||||
}
|
||||
}
|
||||
|
||||
return w.Flush()
|
||||
}
|
||||
|
||||
func init() {
|
||||
disksCmd.Flags().BoolVarP(&disksCmdFlags.insecure, "insecure", "i", false, "get disks using the insecure (encrypted with no auth) maintenance service")
|
||||
addCommand(disksCmd)
|
||||
}
|
||||
|
||||
78
cmd/talosctl/cmd/talos/wipe.go
Normal file
78
cmd/talosctl/cmd/talos/wipe.go
Normal file
@ -0,0 +1,78 @@
|
||||
// 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 talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/siderolabs/gen/xslices"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/api/storage"
|
||||
"github.com/siderolabs/talos/pkg/machinery/client"
|
||||
)
|
||||
|
||||
// wipeCmd represents the wipe command.
|
||||
var wipeCmd = &cobra.Command{
|
||||
Use: "wipe",
|
||||
Short: "Wipe block device or volumes",
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
|
||||
var wipeDiskCmdFlags struct {
|
||||
wipeMethod string
|
||||
skipVolumeCheck bool
|
||||
}
|
||||
|
||||
// wipeDiskCmd represents the wipe disk command.
|
||||
var wipeDiskCmd = &cobra.Command{
|
||||
Use: "disk <device names>...",
|
||||
Short: "Wipe a block device (disk or partition) which is not used as a volume",
|
||||
Long: `Wipe a block device (disk or partition) which is not used as a volume.
|
||||
|
||||
Use device names as arguments, for example: vda or sda5.`,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return WithClient(func(ctx context.Context, c *client.Client) error {
|
||||
method, ok := storage.BlockDeviceWipeDescriptor_Method_value[wipeDiskCmdFlags.wipeMethod]
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid wipe method %q", wipeDiskCmdFlags.wipeMethod)
|
||||
}
|
||||
|
||||
return c.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
|
||||
Devices: xslices.Map(args, func(devName string) *storage.BlockDeviceWipeDescriptor {
|
||||
return &storage.BlockDeviceWipeDescriptor{
|
||||
Device: devName,
|
||||
Method: storage.BlockDeviceWipeDescriptor_Method(method),
|
||||
SkipVolumeCheck: wipeDiskCmdFlags.skipVolumeCheck,
|
||||
}
|
||||
}),
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
func wipeMethodValues() []string {
|
||||
var method storage.BlockDeviceWipeDescriptor_Method
|
||||
|
||||
values := make([]string, method.Descriptor().Values().Len())
|
||||
|
||||
for idx := range method.Descriptor().Values().Len() {
|
||||
values[idx] = storage.BlockDeviceWipeDescriptor_Method_name[int32(idx)]
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
func init() {
|
||||
addCommand(wipeCmd)
|
||||
|
||||
wipeDiskCmd.Flags().StringVar(&wipeDiskCmdFlags.wipeMethod, "method", wipeMethodValues()[0], fmt.Sprintf("wipe method to use %s", wipeMethodValues()))
|
||||
wipeDiskCmd.Flags().BoolVar(&wipeDiskCmdFlags.skipVolumeCheck, "skip-volume-check", false, "skip volume check")
|
||||
wipeDiskCmd.Flags().MarkHidden("skip-volume-check") //nolint:errcheck
|
||||
|
||||
wipeCmd.AddCommand(wipeDiskCmd)
|
||||
}
|
||||
2
go.mod
2
go.mod
@ -140,7 +140,7 @@ require (
|
||||
github.com/siderolabs/gen v0.7.0
|
||||
github.com/siderolabs/go-api-signature v0.3.6
|
||||
github.com/siderolabs/go-blockdevice v0.4.8
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.4
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.5
|
||||
github.com/siderolabs/go-circular v0.2.1
|
||||
github.com/siderolabs/go-cmd v0.1.3
|
||||
github.com/siderolabs/go-copy v0.1.0
|
||||
|
||||
4
go.sum
4
go.sum
@ -648,8 +648,8 @@ github.com/siderolabs/go-api-signature v0.3.6 h1:wDIsXbpl7Oa/FXvxB6uz4VL9INA9fmr
|
||||
github.com/siderolabs/go-api-signature v0.3.6/go.mod h1:hoH13AfunHflxbXfh+NoploqV13ZTDfQ1mQJWNVSW9U=
|
||||
github.com/siderolabs/go-blockdevice v0.4.8 h1:KfdWvIx0Jft5YVuCsFIJFwjWEF1oqtzkgX9PeU9cX4c=
|
||||
github.com/siderolabs/go-blockdevice v0.4.8/go.mod h1:4PeOuk71pReJj1JQEXDE7kIIQJPVe8a+HZQa+qjxSEA=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.4 h1:+5umLlCtwJL0zkjExVr5liwDQtmK2vM2hALDfQMGSTk=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.4/go.mod h1:74htzCV913UzaLZ4H+NBXkwWlYnBJIq5m/379ZEcu8w=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.5 h1:VLmIdDB/1P30Inrpe94FQAz4WUpByGwun5ZeTekxIQc=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.5/go.mod h1:74htzCV913UzaLZ4H+NBXkwWlYnBJIq5m/379ZEcu8w=
|
||||
github.com/siderolabs/go-circular v0.2.1 h1:a++iVCn9jyhICX3POQZZX8n72p2h5JGdGU6w1ulmpcA=
|
||||
github.com/siderolabs/go-circular v0.2.1/go.mod h1:ZDItzVyXK+B/XuqTBV5MtQtSv06VI+oCmWGRnNCATo8=
|
||||
github.com/siderolabs/go-cmd v0.1.3 h1:JrgZwqhJQeoec3QRON0LK+fv+0y7d0DyY7zsfkO6ciw=
|
||||
|
||||
@ -96,6 +96,18 @@ configuration option `.skipFallback` can be used to disable this behavior both f
|
||||
description = """\
|
||||
Talos now supports matching on permanent hardware (MAC) address of the network interfaces.
|
||||
This is specifically useful to match bond members, as they change their hardware addresses when they become part of the bond.
|
||||
"""
|
||||
|
||||
[notes.talosctl-disk]
|
||||
title = "talosctl disks"
|
||||
description = """\
|
||||
The command `talosctl disks` was removed, please use `talosctl get disks`, `talosctl get systemdisk`, and `talosctl get blockdevices` instead.
|
||||
"""
|
||||
|
||||
[notes.talosctl-wipe]
|
||||
title = "talosctl wipe"
|
||||
description = """\
|
||||
The new command `talosctl wipe disk` allows to wipe a disk or a partition which is not used as a volume.
|
||||
"""
|
||||
|
||||
[make_deps]
|
||||
|
||||
@ -107,6 +107,11 @@ func HandleEncryptionWithHandler(ctx context.Context, logger *zap.Logger, volume
|
||||
return xerrors.NewTaggedf[Retryable]("error opening encrypted volume: %w", err)
|
||||
}
|
||||
|
||||
encryptedPath, err = filepath.EvalSymlinks(encryptedPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error resolving symlink: %w", err)
|
||||
}
|
||||
|
||||
volumeContext.Status.Phase = block.VolumePhasePrepared
|
||||
volumeContext.Status.MountLocation = encryptedPath
|
||||
volumeContext.Status.EncryptionProvider = volumeContext.Cfg.TypedSpec().Encryption.Provider
|
||||
|
||||
@ -99,7 +99,8 @@ var rules = map[string]role.Set{
|
||||
"/cosi.resource.State/Update": role.MakeSet(role.Admin),
|
||||
"/cosi.resource.State/Watch": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
|
||||
"/storage.StorageService/Disks": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
"/storage.StorageService/Disks": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
"/storage.StorageService/BlockDeviceWipe": role.MakeSet(role.Admin),
|
||||
|
||||
"/time.TimeService/Time": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
"/time.TimeService/TimeCheck": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
|
||||
@ -70,7 +70,12 @@ func (s *Server) Register(obj *grpc.Server) {
|
||||
resourceState := s.controller.Runtime().State().V1Alpha2().Resources()
|
||||
resourceState = state.WrapCore(state.Filter(resourceState, resources.AccessPolicy(resourceState)))
|
||||
|
||||
storage.RegisterStorageServiceServer(obj, &storaged.Server{Controller: s.controller})
|
||||
storage.RegisterStorageServiceServer(obj,
|
||||
&storaged.Server{
|
||||
Controller: s.controller,
|
||||
MaintenanceMode: true,
|
||||
},
|
||||
)
|
||||
machine.RegisterMachineServiceServer(obj, s)
|
||||
cosiv1alpha1.RegisterStateServer(obj, server.NewState(resourceState))
|
||||
}
|
||||
|
||||
@ -7,15 +7,26 @@ package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/cosi-project/runtime/pkg/safe"
|
||||
"github.com/cosi-project/runtime/pkg/state"
|
||||
"github.com/siderolabs/gen/xslices"
|
||||
"github.com/siderolabs/go-blockdevice/v2/blkid"
|
||||
blockdev "github.com/siderolabs/go-blockdevice/v2/block"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/siderolabs/talos/pkg/grpc/middleware/authz"
|
||||
"github.com/siderolabs/talos/pkg/machinery/api/storage"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/block"
|
||||
"github.com/siderolabs/talos/pkg/machinery/role"
|
||||
)
|
||||
|
||||
// Server implements storage.StorageService.
|
||||
@ -23,7 +34,8 @@ import (
|
||||
// It is only kept here for compatibility purposes, proper API is to query `block.Disk` resources.
|
||||
type Server struct {
|
||||
storage.UnimplementedStorageServiceServer
|
||||
Controller runtime.Controller
|
||||
Controller runtime.Controller
|
||||
MaintenanceMode bool
|
||||
}
|
||||
|
||||
// Disks implements storage.StorageService.
|
||||
@ -81,3 +93,204 @@ func (s *Server) Disks(ctx context.Context, in *emptypb.Empty) (reply *storage.D
|
||||
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
// BlockDeviceWipe implements storage.StorageService.
|
||||
//
|
||||
// It allows to wipe unused block devices, for blockdevices in use (volumes), use a different method.
|
||||
func (s *Server) BlockDeviceWipe(ctx context.Context, req *storage.BlockDeviceWipeRequest) (*storage.BlockDeviceWipeResponse, error) {
|
||||
// the storage server is included both into machined and maintenance service
|
||||
// in apid/machined mode, the normal authz checks are used before reaching this method
|
||||
// in maintenance mode, do the role check, which maps today to SideroLink API connection
|
||||
if s.MaintenanceMode && !authz.HasRole(ctx, role.Admin) {
|
||||
return nil, status.Error(codes.Unimplemented, "API is not implemented in maintenance mode")
|
||||
}
|
||||
|
||||
// validate the list of devices
|
||||
for _, deviceRequest := range req.GetDevices() {
|
||||
if err := s.validateDeviceForWipe(ctx, deviceRequest.GetDevice(), deviceRequest.GetSkipVolumeCheck()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// perform the actual wipe
|
||||
for _, deviceRequest := range req.GetDevices() {
|
||||
if err := s.wipeDevice(deviceRequest.GetDevice(), deviceRequest.GetMethod()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &storage.BlockDeviceWipeResponse{
|
||||
Messages: []*storage.BlockDeviceWipe{
|
||||
{},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
//nolint:gocyclo,cyclop
|
||||
func (s *Server) validateDeviceForWipe(ctx context.Context, deviceName string, skipVolumeCheck bool) error {
|
||||
// first, resolve the blockdevice and figure out what type it is
|
||||
st := s.Controller.Runtime().State().V1Alpha2().Resources()
|
||||
|
||||
blockdevice, err := safe.StateGetByID[*block.Device](ctx, st, deviceName)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return status.Errorf(codes.NotFound, "blockdevice %q not found", deviceName)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var parent string
|
||||
|
||||
deviceType := blockdevice.TypedSpec().Type
|
||||
|
||||
switch deviceType {
|
||||
case "disk": // supported
|
||||
case "partition": // supported
|
||||
parent = blockdevice.TypedSpec().Parent
|
||||
default:
|
||||
return status.Errorf(codes.InvalidArgument, "blockdevice %q is of unsupported type %q", deviceName, deviceType)
|
||||
}
|
||||
|
||||
// check the disk (or parent)
|
||||
var disk *block.Disk
|
||||
|
||||
if parent != "" {
|
||||
disk, err = safe.StateGetByID[*block.Disk](ctx, st, parent)
|
||||
} else {
|
||||
disk, err = safe.StateGetByID[*block.Disk](ctx, st, deviceName)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get disk (or parent) for %q: %w", deviceName, err)
|
||||
}
|
||||
|
||||
if disk.TypedSpec().Readonly {
|
||||
return status.Errorf(codes.FailedPrecondition, "blockdevice %q is read-only", deviceName)
|
||||
}
|
||||
|
||||
if disk.TypedSpec().CDROM {
|
||||
return status.Errorf(codes.FailedPrecondition, "blockdevice %q is a CD-ROM", deviceName)
|
||||
}
|
||||
|
||||
// secondaries check
|
||||
switch deviceType {
|
||||
case "disk": // for disks, check secondaries even if the partition is used as secondary (track via Disk resource)
|
||||
disks, err := safe.StateListAll[*block.Disk](ctx, st)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for disk := range disks.All() {
|
||||
if slices.Index(disk.TypedSpec().SecondaryDisks, deviceName) != -1 {
|
||||
return status.Errorf(codes.FailedPrecondition, "blockdevice %q is in use by disk %q", deviceName, disk.Metadata().ID())
|
||||
}
|
||||
}
|
||||
case "partition": // for partitions, check secondaries only if the partition is used as a secondary
|
||||
blockdevices, err := safe.StateListAll[*block.Device](ctx, st)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for blockdevice := range blockdevices.All() {
|
||||
if slices.Index(blockdevice.TypedSpec().Secondaries, deviceName) != -1 {
|
||||
return status.Errorf(codes.FailedPrecondition, "blockdevice %q is in use by blockdevice %q", deviceName, blockdevice.Metadata().ID())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if skipVolumeCheck {
|
||||
return nil
|
||||
}
|
||||
|
||||
// volume in use checks
|
||||
volumeStatuses, err := safe.StateListAll[*block.VolumeStatus](ctx, st)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for volumeStatus := range volumeStatuses.All() {
|
||||
for _, location := range []string{
|
||||
filepath.Base(volumeStatus.TypedSpec().Location),
|
||||
filepath.Base(volumeStatus.TypedSpec().MountLocation),
|
||||
} {
|
||||
for _, dev := range []string{deviceName, parent} {
|
||||
if dev == "" || location == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if location == dev {
|
||||
return status.Errorf(codes.FailedPrecondition, "blockdevice %q is in use by volume %q", dev, volumeStatus.Metadata().ID())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if filepath.Base(volumeStatus.TypedSpec().ParentLocation) == deviceName {
|
||||
return status.Errorf(codes.FailedPrecondition, "blockdevice %q is in use by volume %q", deviceName, volumeStatus.Metadata().ID())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// wipeDevice wipes the block device with the given method.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func (s *Server) wipeDevice(deviceName string, method storage.BlockDeviceWipeDescriptor_Method) error {
|
||||
bd, err := blockdev.NewFromPath(filepath.Join("/dev", deviceName), blockdev.OpenForWrite())
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to open block device %q: %v", deviceName, err)
|
||||
}
|
||||
|
||||
defer bd.Close() //nolint:errcheck
|
||||
|
||||
if err = bd.Lock(true); err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to lock block device %q: %v", deviceName, err)
|
||||
}
|
||||
|
||||
defer bd.Unlock() //nolint:errcheck
|
||||
|
||||
switch method {
|
||||
case storage.BlockDeviceWipeDescriptor_ZEROES:
|
||||
log.Printf("wiping block device %q with zeroes", deviceName)
|
||||
|
||||
if method, err := bd.Wipe(); err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to wipe block device %q: %v", deviceName, err)
|
||||
} else {
|
||||
log.Printf("block device %q wiped with method %q", deviceName, method)
|
||||
}
|
||||
case storage.BlockDeviceWipeDescriptor_FAST:
|
||||
log.Printf("wiping block device %q with fast method", deviceName)
|
||||
|
||||
info, err := blkid.Probe(bd.File(), blkid.WithSkipLocking(true))
|
||||
if err == nil && info != nil && len(info.SignatureRanges) > 0 { // probe successful, wipe by signatures
|
||||
if err = bd.FastWipe(xslices.Map(info.SignatureRanges, func(r blkid.SignatureRange) blockdev.Range {
|
||||
return blockdev.Range(r)
|
||||
})...); err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to wipe block device %q: %v", deviceName, err)
|
||||
}
|
||||
|
||||
log.Printf("block device %q wiped by ranges: %s",
|
||||
deviceName,
|
||||
strings.Join(
|
||||
xslices.Map(info.SignatureRanges,
|
||||
func(r blkid.SignatureRange) string {
|
||||
return fmt.Sprintf("%d-%d", r.Offset, r.Offset+r.Size)
|
||||
},
|
||||
),
|
||||
", ",
|
||||
),
|
||||
)
|
||||
} else { // probe failed, use default fast wipe
|
||||
if err = bd.FastWipe(); err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to wipe block device %q: %v", deviceName, err)
|
||||
}
|
||||
|
||||
log.Printf("block device %q wiped with fast method", deviceName)
|
||||
}
|
||||
default:
|
||||
return status.Errorf(codes.InvalidArgument, "unsupported wipe method %s", method)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
190
internal/integration/api/wipe.go
Normal file
190
internal/integration/api/wipe.go
Normal file
@ -0,0 +1,190 @@
|
||||
// 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/.
|
||||
|
||||
//go:build integration_api
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/safe"
|
||||
"github.com/cosi-project/runtime/pkg/state"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
||||
"github.com/siderolabs/talos/internal/integration/base"
|
||||
"github.com/siderolabs/talos/pkg/machinery/api/storage"
|
||||
"github.com/siderolabs/talos/pkg/machinery/client"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/machine"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/block"
|
||||
)
|
||||
|
||||
// WipeSuite ...
|
||||
type WipeSuite struct {
|
||||
base.K8sSuite
|
||||
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
// SuiteName ...
|
||||
func (suite *WipeSuite) SuiteName() string {
|
||||
return "api.WipeSuite"
|
||||
}
|
||||
|
||||
// SetupTest ...
|
||||
func (suite *WipeSuite) SetupTest() {
|
||||
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 5*time.Minute)
|
||||
|
||||
if !suite.Capabilities().SupportsVolumes {
|
||||
suite.T().Skip("cluster doesn't support volumes")
|
||||
}
|
||||
}
|
||||
|
||||
// TearDownTest ...
|
||||
func (suite *WipeSuite) TearDownTest() {
|
||||
if suite.ctxCancel != nil {
|
||||
suite.ctxCancel()
|
||||
}
|
||||
}
|
||||
|
||||
// TestWipeBlockDeviceInvalid verifies that invalid wipe requests are rejected.
|
||||
func (suite *WipeSuite) TestWipeBlockDeviceInvalid() {
|
||||
node := suite.RandomDiscoveredNodeInternalIP(machine.TypeWorker)
|
||||
nodeCtx := client.WithNode(suite.ctx, node)
|
||||
|
||||
disks, err := safe.StateListAll[*block.Disk](nodeCtx, suite.Client.COSI)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
for disk := range disks.All() {
|
||||
if disk.TypedSpec().Readonly || disk.TypedSpec().CDROM {
|
||||
suite.T().Logf("invalid wipe request for %s at %s", disk.Metadata().ID(), node)
|
||||
|
||||
err = suite.Client.BlockDeviceWipe(nodeCtx, &storage.BlockDeviceWipeRequest{
|
||||
Devices: []*storage.BlockDeviceWipeDescriptor{
|
||||
{
|
||||
Device: disk.Metadata().ID(),
|
||||
},
|
||||
},
|
||||
})
|
||||
suite.Require().Error(err)
|
||||
suite.Assert().Equal(codes.FailedPrecondition, client.StatusCode(err))
|
||||
}
|
||||
}
|
||||
|
||||
err = suite.Client.BlockDeviceWipe(nodeCtx, &storage.BlockDeviceWipeRequest{
|
||||
Devices: []*storage.BlockDeviceWipeDescriptor{
|
||||
{
|
||||
Device: "nosuchdevice",
|
||||
},
|
||||
},
|
||||
})
|
||||
suite.Require().Error(err)
|
||||
suite.Assert().Equal(codes.NotFound, client.StatusCode(err))
|
||||
|
||||
// try to wipe a system disk
|
||||
systemDisk, err := safe.StateGetByID[*block.SystemDisk](nodeCtx, suite.Client.COSI, block.SystemDiskID)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.T().Logf("invalid wipe request for %s at %s", systemDisk.TypedSpec().DiskID, node)
|
||||
err = suite.Client.BlockDeviceWipe(nodeCtx, &storage.BlockDeviceWipeRequest{
|
||||
Devices: []*storage.BlockDeviceWipeDescriptor{
|
||||
{
|
||||
Device: systemDisk.TypedSpec().DiskID,
|
||||
},
|
||||
},
|
||||
})
|
||||
suite.Require().Error(err)
|
||||
suite.Assert().Equal(codes.FailedPrecondition, client.StatusCode(err))
|
||||
}
|
||||
|
||||
// TestWipeFilesystem verifies that the filesystem can be wiped.
|
||||
func (suite *WipeSuite) TestWipeFilesystem() {
|
||||
if testing.Short() {
|
||||
suite.T().Skip("skipping test in short mode.")
|
||||
}
|
||||
|
||||
if suite.Cluster == nil || suite.Cluster.Provisioner() != base.ProvisionerQEMU {
|
||||
suite.T().Skip("skipping test for non-qemu provisioner")
|
||||
}
|
||||
|
||||
node := suite.RandomDiscoveredNodeInternalIP(machine.TypeWorker)
|
||||
|
||||
k8sNode, err := suite.GetK8sNodeByInternalIP(suite.ctx, node)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
nodeName := k8sNode.Name
|
||||
|
||||
suite.T().Logf("creating filesystem on %s/%s", node, nodeName)
|
||||
|
||||
userDisks, err := suite.UserDisks(suite.ctx, node)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
if len(userDisks) < 1 {
|
||||
suite.T().Skipf("skipping test, not enough user disks available on node %s/%s: %q", node, nodeName, userDisks)
|
||||
}
|
||||
|
||||
userDisk := userDisks[0]
|
||||
|
||||
podDef, err := suite.NewPrivilegedPod("fs-format")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
podDef = podDef.WithNodeName(nodeName)
|
||||
|
||||
suite.Require().NoError(podDef.Create(suite.ctx, 5*time.Minute))
|
||||
|
||||
defer podDef.Delete(suite.ctx) //nolint:errcheck
|
||||
|
||||
_, _, err = podDef.Exec(
|
||||
suite.ctx,
|
||||
fmt.Sprintf("nsenter --mount=/proc/1/ns/mnt -- mkfs.xfs %s", userDisk),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// now Talos should report the disk as xfs formatted
|
||||
deviceName := filepath.Base(userDisk)
|
||||
|
||||
nodeCtx := client.WithNode(suite.ctx, node)
|
||||
|
||||
// wait for Talos to discover xfs
|
||||
_, err = suite.Client.COSI.WatchFor(nodeCtx,
|
||||
block.NewDiscoveredVolume(block.NamespaceName, deviceName).Metadata(),
|
||||
state.WithEventTypes(state.Created, state.Updated),
|
||||
state.WithCondition(func(r resource.Resource) (bool, error) {
|
||||
return r.(*block.DiscoveredVolume).TypedSpec().Name == "xfs", nil
|
||||
}),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.T().Logf("xfs filesystem created on %s/%s", node, nodeName)
|
||||
|
||||
// wipe the filesystem
|
||||
err = suite.Client.BlockDeviceWipe(nodeCtx, &storage.BlockDeviceWipeRequest{
|
||||
Devices: []*storage.BlockDeviceWipeDescriptor{
|
||||
{
|
||||
Device: deviceName,
|
||||
},
|
||||
},
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// wait for Talos to discover that the disk is wiped
|
||||
_, err = suite.Client.COSI.WatchFor(nodeCtx,
|
||||
block.NewDiscoveredVolume(block.NamespaceName, deviceName).Metadata(),
|
||||
state.WithEventTypes(state.Created, state.Updated),
|
||||
state.WithCondition(func(r resource.Resource) (bool, error) {
|
||||
return r.(*block.DiscoveredVolume).TypedSpec().Name == "", nil
|
||||
}),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
func init() {
|
||||
allSuites = append(allSuites, new(WipeSuite))
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
// 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/.
|
||||
|
||||
//go:build integration_cli
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"github.com/siderolabs/talos/internal/integration/base"
|
||||
)
|
||||
|
||||
// DisksSuite verifies dmesg command.
|
||||
type DisksSuite struct {
|
||||
base.CLISuite
|
||||
}
|
||||
|
||||
// SuiteName ...
|
||||
func (suite *DisksSuite) SuiteName() string {
|
||||
return "cli.DisksSuite"
|
||||
}
|
||||
|
||||
// TestSuccess runs comand with success.
|
||||
func (suite *DisksSuite) TestSuccess() {
|
||||
if suite.Cluster != nil && suite.Cluster.Provisioner() == "docker" {
|
||||
suite.T().Skip("docker provisioner doesn't support disks command")
|
||||
}
|
||||
|
||||
suite.RunCLI([]string{"disks", "--nodes", suite.RandomDiscoveredNodeInternalIP()})
|
||||
}
|
||||
|
||||
func init() {
|
||||
allSuites = append(allSuites, new(DisksSuite))
|
||||
}
|
||||
@ -82,6 +82,54 @@ func (Disk_DiskType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_storage_storage_proto_rawDescGZIP(), []int{0, 0}
|
||||
}
|
||||
|
||||
type BlockDeviceWipeDescriptor_Method int32
|
||||
|
||||
const (
|
||||
// Fast wipe - wipe only filesystem signatures.
|
||||
BlockDeviceWipeDescriptor_FAST BlockDeviceWipeDescriptor_Method = 0
|
||||
// Zeroes wipe - wipe by overwriting with zeroes (might be slow depending on the disk size and available hardware features).
|
||||
BlockDeviceWipeDescriptor_ZEROES BlockDeviceWipeDescriptor_Method = 1
|
||||
)
|
||||
|
||||
// Enum value maps for BlockDeviceWipeDescriptor_Method.
|
||||
var (
|
||||
BlockDeviceWipeDescriptor_Method_name = map[int32]string{
|
||||
0: "FAST",
|
||||
1: "ZEROES",
|
||||
}
|
||||
BlockDeviceWipeDescriptor_Method_value = map[string]int32{
|
||||
"FAST": 0,
|
||||
"ZEROES": 1,
|
||||
}
|
||||
)
|
||||
|
||||
func (x BlockDeviceWipeDescriptor_Method) Enum() *BlockDeviceWipeDescriptor_Method {
|
||||
p := new(BlockDeviceWipeDescriptor_Method)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x BlockDeviceWipeDescriptor_Method) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (BlockDeviceWipeDescriptor_Method) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_storage_storage_proto_enumTypes[1].Descriptor()
|
||||
}
|
||||
|
||||
func (BlockDeviceWipeDescriptor_Method) Type() protoreflect.EnumType {
|
||||
return &file_storage_storage_proto_enumTypes[1]
|
||||
}
|
||||
|
||||
func (x BlockDeviceWipeDescriptor_Method) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BlockDeviceWipeDescriptor_Method.Descriptor instead.
|
||||
func (BlockDeviceWipeDescriptor_Method) EnumDescriptor() ([]byte, []int) {
|
||||
return file_storage_storage_proto_rawDescGZIP(), []int{4, 0}
|
||||
}
|
||||
|
||||
// Disk represents a disk.
|
||||
type Disk struct {
|
||||
state protoimpl.MessageState
|
||||
@ -336,6 +384,212 @@ func (x *DisksResponse) GetMessages() []*Disks {
|
||||
return nil
|
||||
}
|
||||
|
||||
type BlockDeviceWipeRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Devices []*BlockDeviceWipeDescriptor `protobuf:"bytes,1,rep,name=devices,proto3" json:"devices,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeRequest) Reset() {
|
||||
*x = BlockDeviceWipeRequest{}
|
||||
mi := &file_storage_storage_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BlockDeviceWipeRequest) ProtoMessage() {}
|
||||
|
||||
func (x *BlockDeviceWipeRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_storage_storage_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BlockDeviceWipeRequest.ProtoReflect.Descriptor instead.
|
||||
func (*BlockDeviceWipeRequest) Descriptor() ([]byte, []int) {
|
||||
return file_storage_storage_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeRequest) GetDevices() []*BlockDeviceWipeDescriptor {
|
||||
if x != nil {
|
||||
return x.Devices
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BlockDeviceWipeDescriptor represents a single block device to be wiped.
|
||||
//
|
||||
// The device can be either a full disk (e.g. vda) or a partition (vda5).
|
||||
// The device should not be used in any of active volumes.
|
||||
// The device should not be used as a secondary (e.g. part of LVM).
|
||||
type BlockDeviceWipeDescriptor struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Device name to wipe (e.g. sda or sda5).
|
||||
//
|
||||
// The name should be submitted without `/dev/` prefix.
|
||||
Device string `protobuf:"bytes,1,opt,name=device,proto3" json:"device,omitempty"`
|
||||
// Wipe method to use.
|
||||
Method BlockDeviceWipeDescriptor_Method `protobuf:"varint,2,opt,name=method,proto3,enum=storage.BlockDeviceWipeDescriptor_Method" json:"method,omitempty"`
|
||||
// Skip the volume in use check.
|
||||
SkipVolumeCheck bool `protobuf:"varint,3,opt,name=skip_volume_check,json=skipVolumeCheck,proto3" json:"skip_volume_check,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeDescriptor) Reset() {
|
||||
*x = BlockDeviceWipeDescriptor{}
|
||||
mi := &file_storage_storage_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeDescriptor) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BlockDeviceWipeDescriptor) ProtoMessage() {}
|
||||
|
||||
func (x *BlockDeviceWipeDescriptor) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_storage_storage_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BlockDeviceWipeDescriptor.ProtoReflect.Descriptor instead.
|
||||
func (*BlockDeviceWipeDescriptor) Descriptor() ([]byte, []int) {
|
||||
return file_storage_storage_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeDescriptor) GetDevice() string {
|
||||
if x != nil {
|
||||
return x.Device
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeDescriptor) GetMethod() BlockDeviceWipeDescriptor_Method {
|
||||
if x != nil {
|
||||
return x.Method
|
||||
}
|
||||
return BlockDeviceWipeDescriptor_FAST
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeDescriptor) GetSkipVolumeCheck() bool {
|
||||
if x != nil {
|
||||
return x.SkipVolumeCheck
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type BlockDeviceWipeResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Messages []*BlockDeviceWipe `protobuf:"bytes,1,rep,name=messages,proto3" json:"messages,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeResponse) Reset() {
|
||||
*x = BlockDeviceWipeResponse{}
|
||||
mi := &file_storage_storage_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BlockDeviceWipeResponse) ProtoMessage() {}
|
||||
|
||||
func (x *BlockDeviceWipeResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_storage_storage_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BlockDeviceWipeResponse.ProtoReflect.Descriptor instead.
|
||||
func (*BlockDeviceWipeResponse) Descriptor() ([]byte, []int) {
|
||||
return file_storage_storage_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipeResponse) GetMessages() []*BlockDeviceWipe {
|
||||
if x != nil {
|
||||
return x.Messages
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BlockDeviceWipe struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Metadata *common.Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipe) Reset() {
|
||||
*x = BlockDeviceWipe{}
|
||||
mi := &file_storage_storage_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipe) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BlockDeviceWipe) ProtoMessage() {}
|
||||
|
||||
func (x *BlockDeviceWipe) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_storage_storage_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BlockDeviceWipe.ProtoReflect.Descriptor instead.
|
||||
func (*BlockDeviceWipe) Descriptor() ([]byte, []int) {
|
||||
return file_storage_storage_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *BlockDeviceWipe) GetMetadata() *common.Metadata {
|
||||
if x != nil {
|
||||
return x.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_storage_storage_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_storage_storage_proto_rawDesc = []byte{
|
||||
@ -380,17 +634,49 @@ var file_storage_storage_proto_rawDesc = []byte{
|
||||
0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x08, 0x6d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x52, 0x08, 0x6d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x32, 0x49, 0x0a, 0x0e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x56, 0x0a, 0x16, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44,
|
||||
0x65, 0x76, 0x69, 0x63, 0x65, 0x57, 0x69, 0x70, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x12, 0x3c, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x22, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x57, 0x69, 0x70, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0xc2,
|
||||
0x01, 0x0a, 0x19, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x57, 0x69,
|
||||
0x70, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65,
|
||||
0x76, 0x69, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x42,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x57, 0x69, 0x70, 0x65, 0x44, 0x65,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52,
|
||||
0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x6b, 0x69, 0x70, 0x5f,
|
||||
0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x43, 0x68,
|
||||
0x65, 0x63, 0x6b, 0x22, 0x1e, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x08, 0x0a,
|
||||
0x04, 0x46, 0x41, 0x53, 0x54, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x5a, 0x45, 0x52, 0x4f, 0x45,
|
||||
0x53, 0x10, 0x01, 0x22, 0x4f, 0x0a, 0x17, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x76, 0x69,
|
||||
0x63, 0x65, 0x57, 0x69, 0x70, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34,
|
||||
0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x18, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x57, 0x69, 0x70, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x73, 0x22, 0x3f, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x76,
|
||||
0x69, 0x63, 0x65, 0x57, 0x69, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
||||
0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74,
|
||||
0x61, 0x64, 0x61, 0x74, 0x61, 0x32, 0x9f, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67,
|
||||
0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x44, 0x69, 0x73, 0x6b,
|
||||
0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x73, 0x74, 0x6f, 0x72,
|
||||
0x61, 0x67, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x42, 0x4e, 0x0a, 0x15, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x61,
|
||||
0x70, 0x69, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5a, 0x35, 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, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
|
||||
0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x65, 0x12, 0x54, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
|
||||
0x57, 0x69, 0x70, 0x65, 0x12, 0x1f, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x42,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x57, 0x69, 0x70, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e,
|
||||
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x57, 0x69, 0x70, 0x65, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4e, 0x0a, 0x15, 0x64, 0x65, 0x76, 0x2e, 0x74,
|
||||
0x61, 0x6c, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
|
||||
0x5a, 0x35, 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,
|
||||
0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -405,28 +691,39 @@ func file_storage_storage_proto_rawDescGZIP() []byte {
|
||||
return file_storage_storage_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_storage_storage_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_storage_storage_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||
var file_storage_storage_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_storage_storage_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_storage_storage_proto_goTypes = []any{
|
||||
(Disk_DiskType)(0), // 0: storage.Disk.DiskType
|
||||
(*Disk)(nil), // 1: storage.Disk
|
||||
(*Disks)(nil), // 2: storage.Disks
|
||||
(*DisksResponse)(nil), // 3: storage.DisksResponse
|
||||
(*common.Metadata)(nil), // 4: common.Metadata
|
||||
(*emptypb.Empty)(nil), // 5: google.protobuf.Empty
|
||||
(Disk_DiskType)(0), // 0: storage.Disk.DiskType
|
||||
(BlockDeviceWipeDescriptor_Method)(0), // 1: storage.BlockDeviceWipeDescriptor.Method
|
||||
(*Disk)(nil), // 2: storage.Disk
|
||||
(*Disks)(nil), // 3: storage.Disks
|
||||
(*DisksResponse)(nil), // 4: storage.DisksResponse
|
||||
(*BlockDeviceWipeRequest)(nil), // 5: storage.BlockDeviceWipeRequest
|
||||
(*BlockDeviceWipeDescriptor)(nil), // 6: storage.BlockDeviceWipeDescriptor
|
||||
(*BlockDeviceWipeResponse)(nil), // 7: storage.BlockDeviceWipeResponse
|
||||
(*BlockDeviceWipe)(nil), // 8: storage.BlockDeviceWipe
|
||||
(*common.Metadata)(nil), // 9: common.Metadata
|
||||
(*emptypb.Empty)(nil), // 10: google.protobuf.Empty
|
||||
}
|
||||
var file_storage_storage_proto_depIdxs = []int32{
|
||||
0, // 0: storage.Disk.type:type_name -> storage.Disk.DiskType
|
||||
4, // 1: storage.Disks.metadata:type_name -> common.Metadata
|
||||
1, // 2: storage.Disks.disks:type_name -> storage.Disk
|
||||
2, // 3: storage.DisksResponse.messages:type_name -> storage.Disks
|
||||
5, // 4: storage.StorageService.Disks:input_type -> google.protobuf.Empty
|
||||
3, // 5: storage.StorageService.Disks:output_type -> storage.DisksResponse
|
||||
5, // [5:6] is the sub-list for method output_type
|
||||
4, // [4:5] is the sub-list for method input_type
|
||||
4, // [4:4] is the sub-list for extension type_name
|
||||
4, // [4:4] is the sub-list for extension extendee
|
||||
0, // [0:4] is the sub-list for field type_name
|
||||
0, // 0: storage.Disk.type:type_name -> storage.Disk.DiskType
|
||||
9, // 1: storage.Disks.metadata:type_name -> common.Metadata
|
||||
2, // 2: storage.Disks.disks:type_name -> storage.Disk
|
||||
3, // 3: storage.DisksResponse.messages:type_name -> storage.Disks
|
||||
6, // 4: storage.BlockDeviceWipeRequest.devices:type_name -> storage.BlockDeviceWipeDescriptor
|
||||
1, // 5: storage.BlockDeviceWipeDescriptor.method:type_name -> storage.BlockDeviceWipeDescriptor.Method
|
||||
8, // 6: storage.BlockDeviceWipeResponse.messages:type_name -> storage.BlockDeviceWipe
|
||||
9, // 7: storage.BlockDeviceWipe.metadata:type_name -> common.Metadata
|
||||
10, // 8: storage.StorageService.Disks:input_type -> google.protobuf.Empty
|
||||
5, // 9: storage.StorageService.BlockDeviceWipe:input_type -> storage.BlockDeviceWipeRequest
|
||||
4, // 10: storage.StorageService.Disks:output_type -> storage.DisksResponse
|
||||
7, // 11: storage.StorageService.BlockDeviceWipe:output_type -> storage.BlockDeviceWipeResponse
|
||||
10, // [10:12] is the sub-list for method output_type
|
||||
8, // [8:10] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
8, // [8:8] is the sub-list for extension extendee
|
||||
0, // [0:8] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_storage_storage_proto_init() }
|
||||
@ -439,8 +736,8 @@ func file_storage_storage_proto_init() {
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_storage_storage_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 3,
|
||||
NumEnums: 2,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@ -21,7 +21,8 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
StorageService_Disks_FullMethodName = "/storage.StorageService/Disks"
|
||||
StorageService_Disks_FullMethodName = "/storage.StorageService/Disks"
|
||||
StorageService_BlockDeviceWipe_FullMethodName = "/storage.StorageService/BlockDeviceWipe"
|
||||
)
|
||||
|
||||
// StorageServiceClient is the client API for StorageService service.
|
||||
@ -31,6 +32,12 @@ const (
|
||||
// StorageService represents the storage service.
|
||||
type StorageServiceClient interface {
|
||||
Disks(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*DisksResponse, error)
|
||||
// BlockDeviceWipe performs a wipe of the blockdevice (partition or disk).
|
||||
//
|
||||
// The method doesn't require a reboot, and it can only wipe blockdevices which are not
|
||||
// being used as volumes at the moment.
|
||||
// Wiping of volumes requires a different API.
|
||||
BlockDeviceWipe(ctx context.Context, in *BlockDeviceWipeRequest, opts ...grpc.CallOption) (*BlockDeviceWipeResponse, error)
|
||||
}
|
||||
|
||||
type storageServiceClient struct {
|
||||
@ -51,6 +58,16 @@ func (c *storageServiceClient) Disks(ctx context.Context, in *emptypb.Empty, opt
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *storageServiceClient) BlockDeviceWipe(ctx context.Context, in *BlockDeviceWipeRequest, opts ...grpc.CallOption) (*BlockDeviceWipeResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(BlockDeviceWipeResponse)
|
||||
err := c.cc.Invoke(ctx, StorageService_BlockDeviceWipe_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// StorageServiceServer is the server API for StorageService service.
|
||||
// All implementations must embed UnimplementedStorageServiceServer
|
||||
// for forward compatibility.
|
||||
@ -58,6 +75,12 @@ func (c *storageServiceClient) Disks(ctx context.Context, in *emptypb.Empty, opt
|
||||
// StorageService represents the storage service.
|
||||
type StorageServiceServer interface {
|
||||
Disks(context.Context, *emptypb.Empty) (*DisksResponse, error)
|
||||
// BlockDeviceWipe performs a wipe of the blockdevice (partition or disk).
|
||||
//
|
||||
// The method doesn't require a reboot, and it can only wipe blockdevices which are not
|
||||
// being used as volumes at the moment.
|
||||
// Wiping of volumes requires a different API.
|
||||
BlockDeviceWipe(context.Context, *BlockDeviceWipeRequest) (*BlockDeviceWipeResponse, error)
|
||||
mustEmbedUnimplementedStorageServiceServer()
|
||||
}
|
||||
|
||||
@ -71,6 +94,9 @@ type UnimplementedStorageServiceServer struct{}
|
||||
func (UnimplementedStorageServiceServer) Disks(context.Context, *emptypb.Empty) (*DisksResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Disks not implemented")
|
||||
}
|
||||
func (UnimplementedStorageServiceServer) BlockDeviceWipe(context.Context, *BlockDeviceWipeRequest) (*BlockDeviceWipeResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BlockDeviceWipe not implemented")
|
||||
}
|
||||
func (UnimplementedStorageServiceServer) mustEmbedUnimplementedStorageServiceServer() {}
|
||||
func (UnimplementedStorageServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
@ -110,6 +136,24 @@ func _StorageService_Disks_Handler(srv interface{}, ctx context.Context, dec fun
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _StorageService_BlockDeviceWipe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(BlockDeviceWipeRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(StorageServiceServer).BlockDeviceWipe(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: StorageService_BlockDeviceWipe_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(StorageServiceServer).BlockDeviceWipe(ctx, req.(*BlockDeviceWipeRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// StorageService_ServiceDesc is the grpc.ServiceDesc for StorageService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@ -121,6 +165,10 @@ var StorageService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Disks",
|
||||
Handler: _StorageService_Disks_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "BlockDeviceWipe",
|
||||
Handler: _StorageService_BlockDeviceWipe_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "storage/storage.proto",
|
||||
|
||||
@ -260,6 +260,206 @@ func (m *DisksResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeRequest) MarshalVT() (dAtA []byte, err error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
size := m.SizeVT()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeRequest) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.unknownFields != nil {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if len(m.Devices) > 0 {
|
||||
for iNdEx := len(m.Devices) - 1; iNdEx >= 0; iNdEx-- {
|
||||
size, err := m.Devices[iNdEx].MarshalToSizedBufferVT(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeDescriptor) MarshalVT() (dAtA []byte, err error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
size := m.SizeVT()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeDescriptor) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeDescriptor) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.unknownFields != nil {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if m.SkipVolumeCheck {
|
||||
i--
|
||||
if m.SkipVolumeCheck {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
if m.Method != 0 {
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Method))
|
||||
i--
|
||||
dAtA[i] = 0x10
|
||||
}
|
||||
if len(m.Device) > 0 {
|
||||
i -= len(m.Device)
|
||||
copy(dAtA[i:], m.Device)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Device)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeResponse) MarshalVT() (dAtA []byte, err error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
size := m.SizeVT()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeResponse) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.unknownFields != nil {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if len(m.Messages) > 0 {
|
||||
for iNdEx := len(m.Messages) - 1; iNdEx >= 0; iNdEx-- {
|
||||
size, err := m.Messages[iNdEx].MarshalToSizedBufferVT(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipe) MarshalVT() (dAtA []byte, err error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
size := m.SizeVT()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipe) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipe) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.unknownFields != nil {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if m.Metadata != nil {
|
||||
if vtmsg, ok := interface{}(m.Metadata).(interface {
|
||||
MarshalToSizedBufferVT([]byte) (int, error)
|
||||
}); ok {
|
||||
size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
|
||||
} else {
|
||||
encoded, err := proto.Marshal(m.Metadata)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= len(encoded)
|
||||
copy(dAtA[i:], encoded)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *Disk) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@ -360,6 +560,78 @@ func (m *DisksResponse) SizeVT() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeRequest) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Devices) > 0 {
|
||||
for _, e := range m.Devices {
|
||||
l = e.SizeVT()
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeDescriptor) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Device)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
if m.Method != 0 {
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(m.Method))
|
||||
}
|
||||
if m.SkipVolumeCheck {
|
||||
n += 2
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipeResponse) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Messages) > 0 {
|
||||
for _, e := range m.Messages {
|
||||
l = e.SizeVT()
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *BlockDeviceWipe) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.Metadata != nil {
|
||||
if size, ok := interface{}(m.Metadata).(interface {
|
||||
SizeVT() int
|
||||
}); ok {
|
||||
l = size.SizeVT()
|
||||
} else {
|
||||
l = proto.Size(m.Metadata)
|
||||
}
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Disk) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
@ -991,3 +1263,390 @@ func (m *DisksResponse) UnmarshalVT(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *BlockDeviceWipeRequest) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: BlockDeviceWipeRequest: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: BlockDeviceWipeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Devices", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Devices = append(m.Devices, &BlockDeviceWipeDescriptor{})
|
||||
if err := m.Devices[len(m.Devices)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *BlockDeviceWipeDescriptor) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: BlockDeviceWipeDescriptor: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: BlockDeviceWipeDescriptor: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Device", 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.Device = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Method", wireType)
|
||||
}
|
||||
m.Method = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Method |= BlockDeviceWipeDescriptor_Method(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SkipVolumeCheck", 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.SkipVolumeCheck = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *BlockDeviceWipeResponse) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: BlockDeviceWipeResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: BlockDeviceWipeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Messages", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Messages = append(m.Messages, &BlockDeviceWipe{})
|
||||
if err := m.Messages[len(m.Messages)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *BlockDeviceWipe) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: BlockDeviceWipe: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: BlockDeviceWipe: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Metadata == nil {
|
||||
m.Metadata = &common.Metadata{}
|
||||
}
|
||||
if unmarshal, ok := interface{}(m.Metadata).(interface {
|
||||
UnmarshalVT([]byte) error
|
||||
}); ok {
|
||||
if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Metadata); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1002,3 +1002,12 @@ func (c *Client) ImagePull(ctx context.Context, namespace common.ContainerdNames
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// BlockDeviceWipe wipes a block device which is not used as a volume.
|
||||
func (c *Client) BlockDeviceWipe(ctx context.Context, req *storageapi.BlockDeviceWipeRequest, callOptions ...grpc.CallOption) error {
|
||||
resp, err := c.StorageClient.BlockDeviceWipe(ctx, req, callOptions...)
|
||||
|
||||
_, err = FilterMessages(resp, err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ require (
|
||||
github.com/siderolabs/crypto v0.5.0
|
||||
github.com/siderolabs/gen v0.7.0
|
||||
github.com/siderolabs/go-api-signature v0.3.6
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.4
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.5
|
||||
github.com/siderolabs/go-pointer v1.0.0
|
||||
github.com/siderolabs/net v0.4.0
|
||||
github.com/siderolabs/protoenc v0.2.1
|
||||
|
||||
@ -113,8 +113,8 @@ github.com/siderolabs/gen v0.7.0 h1:uHAt3WD0dof28NHFuguWBbDokaXQraR/HyVxCLw2QCU=
|
||||
github.com/siderolabs/gen v0.7.0/go.mod h1:an3a2Y53O7kUjnnK8Bfu3gewtvnIOu5RTU6HalFtXQQ=
|
||||
github.com/siderolabs/go-api-signature v0.3.6 h1:wDIsXbpl7Oa/FXvxB6uz4VL9INA9fmr3EbmjEZYFJrU=
|
||||
github.com/siderolabs/go-api-signature v0.3.6/go.mod h1:hoH13AfunHflxbXfh+NoploqV13ZTDfQ1mQJWNVSW9U=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.4 h1:+5umLlCtwJL0zkjExVr5liwDQtmK2vM2hALDfQMGSTk=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.4/go.mod h1:74htzCV913UzaLZ4H+NBXkwWlYnBJIq5m/379ZEcu8w=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.5 h1:VLmIdDB/1P30Inrpe94FQAz4WUpByGwun5ZeTekxIQc=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.5/go.mod h1:74htzCV913UzaLZ4H+NBXkwWlYnBJIq5m/379ZEcu8w=
|
||||
github.com/siderolabs/go-pointer v1.0.0 h1:6TshPKep2doDQJAAtHUuHWXbca8ZfyRySjSBT/4GsMU=
|
||||
github.com/siderolabs/go-pointer v1.0.0/go.mod h1:HTRFUNYa3R+k0FFKNv11zgkaCLzEkWVzoYZ433P3kHc=
|
||||
github.com/siderolabs/go-retry v0.3.3 h1:zKV+S1vumtO72E6sYsLlmIdV/G/GcYSBLiEx/c9oCEg=
|
||||
|
||||
@ -493,10 +493,15 @@ description: Talos gRPC API reference.
|
||||
- [SecurityService](#securityapi.SecurityService)
|
||||
|
||||
- [storage/storage.proto](#storage/storage.proto)
|
||||
- [BlockDeviceWipe](#storage.BlockDeviceWipe)
|
||||
- [BlockDeviceWipeDescriptor](#storage.BlockDeviceWipeDescriptor)
|
||||
- [BlockDeviceWipeRequest](#storage.BlockDeviceWipeRequest)
|
||||
- [BlockDeviceWipeResponse](#storage.BlockDeviceWipeResponse)
|
||||
- [Disk](#storage.Disk)
|
||||
- [Disks](#storage.Disks)
|
||||
- [DisksResponse](#storage.DisksResponse)
|
||||
|
||||
- [BlockDeviceWipeDescriptor.Method](#storage.BlockDeviceWipeDescriptor.Method)
|
||||
- [Disk.DiskType](#storage.Disk.DiskType)
|
||||
|
||||
- [StorageService](#storage.StorageService)
|
||||
@ -8488,6 +8493,74 @@ The security service definition.
|
||||
|
||||
|
||||
|
||||
<a name="storage.BlockDeviceWipe"></a>
|
||||
|
||||
### BlockDeviceWipe
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| metadata | [common.Metadata](#common.Metadata) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="storage.BlockDeviceWipeDescriptor"></a>
|
||||
|
||||
### BlockDeviceWipeDescriptor
|
||||
BlockDeviceWipeDescriptor represents a single block device to be wiped.
|
||||
|
||||
The device can be either a full disk (e.g. vda) or a partition (vda5).
|
||||
The device should not be used in any of active volumes.
|
||||
The device should not be used as a secondary (e.g. part of LVM).
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| device | [string](#string) | | Device name to wipe (e.g. sda or sda5).
|
||||
|
||||
The name should be submitted without `/dev/` prefix. |
|
||||
| method | [BlockDeviceWipeDescriptor.Method](#storage.BlockDeviceWipeDescriptor.Method) | | Wipe method to use. |
|
||||
| skip_volume_check | [bool](#bool) | | Skip the volume in use check. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="storage.BlockDeviceWipeRequest"></a>
|
||||
|
||||
### BlockDeviceWipeRequest
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| devices | [BlockDeviceWipeDescriptor](#storage.BlockDeviceWipeDescriptor) | repeated | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="storage.BlockDeviceWipeResponse"></a>
|
||||
|
||||
### BlockDeviceWipeResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| messages | [BlockDeviceWipe](#storage.BlockDeviceWipe) | repeated | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="storage.Disk"></a>
|
||||
|
||||
### Disk
|
||||
@ -8548,6 +8621,18 @@ DisksResponse represents the response of the `Disks` RPC.
|
||||
<!-- end messages -->
|
||||
|
||||
|
||||
<a name="storage.BlockDeviceWipeDescriptor.Method"></a>
|
||||
|
||||
### BlockDeviceWipeDescriptor.Method
|
||||
|
||||
|
||||
| Name | Number | Description |
|
||||
| ---- | ------ | ----------- |
|
||||
| FAST | 0 | Fast wipe - wipe only filesystem signatures. |
|
||||
| ZEROES | 1 | Zeroes wipe - wipe by overwriting with zeroes (might be slow depending on the disk size and available hardware features). |
|
||||
|
||||
|
||||
|
||||
<a name="storage.Disk.DiskType"></a>
|
||||
|
||||
### Disk.DiskType
|
||||
@ -8576,6 +8661,9 @@ StorageService represents the storage service.
|
||||
| Method Name | Request Type | Response Type | Description |
|
||||
| ----------- | ------------ | ------------- | ------------|
|
||||
| Disks | [.google.protobuf.Empty](#google.protobuf.Empty) | [DisksResponse](#storage.DisksResponse) | |
|
||||
| BlockDeviceWipe | [BlockDeviceWipeRequest](#storage.BlockDeviceWipeRequest) | [BlockDeviceWipeResponse](#storage.BlockDeviceWipeResponse) | BlockDeviceWipe performs a wipe of the blockdevice (partition or disk).
|
||||
|
||||
The method doesn't require a reboot, and it can only wipe blockdevices which are not being used as volumes at the moment. Wiping of volumes requires a different API. |
|
||||
|
||||
<!-- end services -->
|
||||
|
||||
|
||||
@ -872,35 +872,6 @@ talosctl dashboard [flags]
|
||||
|
||||
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
|
||||
## talosctl disks
|
||||
|
||||
Get the list of disks from /sys/block on the machine
|
||||
|
||||
```
|
||||
talosctl disks [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for disks
|
||||
-i, --insecure get disks using the insecure (encrypted with no auth) maintenance service
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--cluster string Cluster to connect to if a proxy endpoint is used.
|
||||
--context string Context to be used in command
|
||||
-e, --endpoints strings override default endpoints in Talos configuration
|
||||
-n, --nodes strings target the specified nodes
|
||||
--talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order.
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
|
||||
## talosctl dmesg
|
||||
|
||||
Retrieve kernel logs
|
||||
@ -3162,6 +3133,66 @@ talosctl version [flags]
|
||||
|
||||
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
|
||||
## talosctl wipe disk
|
||||
|
||||
Wipe a block device (disk or partition) which is not used as a volume
|
||||
|
||||
### Synopsis
|
||||
|
||||
Wipe a block device (disk or partition) which is not used as a volume.
|
||||
|
||||
Use device names as arguments, for example: vda or sda5.
|
||||
|
||||
```
|
||||
talosctl wipe disk <device names>... [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for disk
|
||||
--method string wipe method to use [FAST ZEROES] (default "FAST")
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--cluster string Cluster to connect to if a proxy endpoint is used.
|
||||
--context string Context to be used in command
|
||||
-e, --endpoints strings override default endpoints in Talos configuration
|
||||
-n, --nodes strings target the specified nodes
|
||||
--talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order.
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [talosctl wipe](#talosctl-wipe) - Wipe block device or volumes
|
||||
|
||||
## talosctl wipe
|
||||
|
||||
Wipe block device or volumes
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for wipe
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--cluster string Cluster to connect to if a proxy endpoint is used.
|
||||
--context string Context to be used in command
|
||||
-e, --endpoints strings override default endpoints in Talos configuration
|
||||
-n, --nodes strings target the specified nodes
|
||||
--talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order.
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
* [talosctl wipe disk](#talosctl-wipe-disk) - Wipe a block device (disk or partition) which is not used as a volume
|
||||
|
||||
## talosctl
|
||||
|
||||
A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
@ -3189,7 +3220,6 @@ A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
* [talosctl containers](#talosctl-containers) - List containers
|
||||
* [talosctl copy](#talosctl-copy) - Copy data out from the node
|
||||
* [talosctl dashboard](#talosctl-dashboard) - Cluster dashboard with node overview, logs and real-time metrics
|
||||
* [talosctl disks](#talosctl-disks) - Get the list of disks from /sys/block on the machine
|
||||
* [talosctl dmesg](#talosctl-dmesg) - Retrieve kernel logs
|
||||
* [talosctl edit](#talosctl-edit) - Edit a resource from the default editor.
|
||||
* [talosctl etcd](#talosctl-etcd) - Manage etcd
|
||||
@ -3227,4 +3257,5 @@ A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
* [talosctl usage](#talosctl-usage) - Retrieve a disk usage
|
||||
* [talosctl validate](#talosctl-validate) - Validate config
|
||||
* [talosctl version](#talosctl-version) - Prints the version
|
||||
* [talosctl wipe](#talosctl-wipe) - Wipe block device or volumes
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user