mirror of
https://github.com/siderolabs/talos.git
synced 2025-11-02 09:21:13 +01:00
feat: provide disk detection based on new blockdevices
Uses go-siderolabs/go-blockdevice/v2 for all the hard parts, provides new resource `Disk` which describes all disks in the system. Additional resource `SystemDisk` always point to the system disk (based on the location of `META` partition). The `Disks` API (and `talosctl disks`) provides a view now into the `talosctl get disks` to keep backwards compatibility. QEMU provisioner can now create extra disks of various types: IDE, AHCI, SCSI, NVME, this allows to test detection properly. The new resource will be the foundation for volume provisioning (to pick up the disk to provision the volume on). Example: ``` talosctl -n 172.20.0.5 get disks NODE NAMESPACE TYPE ID VERSION SIZE READ ONLY TRANSPORT ROTATIONAL WWID MODEL SERIAL 172.20.0.5 runtime Disk loop0 1 65568768 true 172.20.0.5 runtime Disk nvme0n1 1 10485760000 false nvme nvme.1b36-6465616462656566-51454d55204e564d65204374726c-00000001 QEMU NVMe Ctrl deadbeef 172.20.0.5 runtime Disk sda 1 10485760000 false virtio true QEMU HARDDISK 172.20.0.5 runtime Disk sdb 1 10485760000 false sata true t10.ATA QEMU HARDDISK QM00013 QEMU HARDDISK 172.20.0.5 runtime Disk sdc 1 10485760000 false sata true t10.ATA QEMU HARDDISK QM00001 QEMU HARDDISK 172.20.0.5 runtime Disk vda 1 12884901888 false virtio true ``` Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
parent
8ee0872683
commit
f07b79f4a8
@ -36,3 +36,24 @@ message DiscoveredVolumeSpec {
|
||||
string parent = 16;
|
||||
}
|
||||
|
||||
// DiskSpec is the spec for Disks status.
|
||||
message DiskSpec {
|
||||
uint64 size = 1;
|
||||
uint64 io_size = 2;
|
||||
uint64 sector_size = 3;
|
||||
bool readonly = 4;
|
||||
string model = 5;
|
||||
string serial = 6;
|
||||
string modalias = 7;
|
||||
string wwid = 8;
|
||||
string bus_path = 9;
|
||||
string sub_system = 10;
|
||||
string transport = 11;
|
||||
bool rotational = 12;
|
||||
}
|
||||
|
||||
// SystemDiskSpec is the spec for SystemDisks status.
|
||||
message SystemDiskSpec {
|
||||
string disk_id = 1;
|
||||
}
|
||||
|
||||
|
||||
@ -137,6 +137,7 @@ var (
|
||||
clusterDisks []string
|
||||
extraDisks int
|
||||
extraDiskSize int
|
||||
extraDisksDrivers []string
|
||||
targetArch string
|
||||
clusterWait bool
|
||||
clusterWaitTimeout time.Duration
|
||||
@ -832,10 +833,17 @@ func create(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// append extra disks
|
||||
for range extraDisks {
|
||||
for i := range extraDisks {
|
||||
driver := "ide"
|
||||
|
||||
if i < len(extraDisksDrivers) {
|
||||
driver = extraDisksDrivers[i]
|
||||
}
|
||||
|
||||
disks = append(disks, &provision.Disk{
|
||||
Size: uint64(extraDiskSize) * 1024 * 1024,
|
||||
SkipPreallocate: !clusterDiskPreallocate,
|
||||
Driver: driver,
|
||||
})
|
||||
}
|
||||
|
||||
@ -1045,6 +1053,7 @@ func getDisks() ([]*provision.Disk, error) {
|
||||
{
|
||||
Size: uint64(clusterDiskSize) * 1024 * 1024,
|
||||
SkipPreallocate: !clusterDiskPreallocate,
|
||||
Driver: "virtio",
|
||||
},
|
||||
}
|
||||
|
||||
@ -1092,6 +1101,7 @@ func getDisks() ([]*provision.Disk, error) {
|
||||
Size: diskSize + 2*1024*1024,
|
||||
Partitions: diskPartitions,
|
||||
SkipPreallocate: !clusterDiskPreallocate,
|
||||
Driver: "ide",
|
||||
})
|
||||
}
|
||||
|
||||
@ -1143,6 +1153,7 @@ func init() {
|
||||
createCmd.Flags().BoolVar(&clusterDiskPreallocate, clusterDiskPreallocateFlag, true, "whether disk space should be preallocated")
|
||||
createCmd.Flags().StringSliceVar(&clusterDisks, clusterDisksFlag, []string{}, "list of disks to create for each VM in format: <mount_point1>:<size1>:<mount_point2>:<size2>")
|
||||
createCmd.Flags().IntVar(&extraDisks, "extra-disks", 0, "number of extra disks to create for each worker VM")
|
||||
createCmd.Flags().StringSliceVar(&extraDisksDrivers, "extra-disks-drivers", nil, "driver for each extra disk (virtio, ide, ahci, scsi, nvme)")
|
||||
createCmd.Flags().IntVar(&extraDiskSize, "extra-disks-size", 5*1024, "default limit on disk size in MB (each VM)")
|
||||
createCmd.Flags().StringVar(&targetArch, "arch", stdruntime.GOARCH, "cluster architecture")
|
||||
createCmd.Flags().BoolVar(&clusterWait, "wait", true, "wait for the cluster to be ready before returning")
|
||||
|
||||
2
go.mod
2
go.mod
@ -128,7 +128,7 @@ require (
|
||||
github.com/siderolabs/gen v0.5.0
|
||||
github.com/siderolabs/go-api-signature v0.3.2
|
||||
github.com/siderolabs/go-blockdevice v0.4.7
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.0-20240604163945-81b69bf28eaa
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.0-20240607145058-1a51f162a09e
|
||||
github.com/siderolabs/go-circular v0.2.0
|
||||
github.com/siderolabs/go-cmd v0.1.1
|
||||
github.com/siderolabs/go-copy v0.1.0
|
||||
|
||||
4
go.sum
4
go.sum
@ -661,8 +661,8 @@ github.com/siderolabs/go-api-signature v0.3.2 h1:blqrZF1GM7TWgq7mY7CsR+yQ93u6az0
|
||||
github.com/siderolabs/go-api-signature v0.3.2/go.mod h1:punhUOaXa7LELYBRCUhfgUGH6ieVz68GrP98apCKXj8=
|
||||
github.com/siderolabs/go-blockdevice v0.4.7 h1:2bk4WpEEflGxjrNwp57ye24Pr+cYgAiAeNMWiQOuWbQ=
|
||||
github.com/siderolabs/go-blockdevice v0.4.7/go.mod h1:4PeOuk71pReJj1JQEXDE7kIIQJPVe8a+HZQa+qjxSEA=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.0-20240604163945-81b69bf28eaa h1:OjQLrcis/GuqaqxnIw2dxp4ZzT/zk5p1GI3NxcMxkrA=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.0-20240604163945-81b69bf28eaa/go.mod h1:5GnL7VLNp5/vgiwYP74fi6KuTUfqGcRxQxtto2tzD+I=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.0-20240607145058-1a51f162a09e h1:PQhtHJj3zwaqehthq0fs2TyW8bW/mlOYoHfZIeSYQ3M=
|
||||
github.com/siderolabs/go-blockdevice/v2 v2.0.0-20240607145058-1a51f162a09e/go.mod h1:5GnL7VLNp5/vgiwYP74fi6KuTUfqGcRxQxtto2tzD+I=
|
||||
github.com/siderolabs/go-circular v0.2.0 h1:Xca8zrjF/YsujLbwDSojkKzJe7ngetnpuIJn8N78DJI=
|
||||
github.com/siderolabs/go-circular v0.2.0/go.mod h1:rrYCwHLYWmxqrmZP+LjYtwB2a55lxzQi0Ztu1VpWZSc=
|
||||
github.com/siderolabs/go-cmd v0.1.1 h1:nTouZUSxLeiiEe7hFexSVvaTsY/3O8k1s08BxPRrsps=
|
||||
|
||||
167
internal/app/machined/pkg/controllers/block/disks.go
Normal file
167
internal/app/machined/pkg/controllers/block/disks.go
Normal file
@ -0,0 +1,167 @@
|
||||
// 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 block
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/cosi-project/runtime/pkg/controller"
|
||||
"github.com/cosi-project/runtime/pkg/safe"
|
||||
blkdev "github.com/siderolabs/go-blockdevice/v2/block"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/block"
|
||||
)
|
||||
|
||||
// DisksController provides a detailed view of blockdevices of type 'disk'.
|
||||
type DisksController struct{}
|
||||
|
||||
// Name implements controller.Controller interface.
|
||||
func (ctrl *DisksController) Name() string {
|
||||
return "block.DisksController"
|
||||
}
|
||||
|
||||
// Inputs implements controller.Controller interface.
|
||||
func (ctrl *DisksController) Inputs() []controller.Input {
|
||||
return []controller.Input{
|
||||
{
|
||||
Namespace: block.NamespaceName,
|
||||
Type: block.DeviceType,
|
||||
Kind: controller.InputWeak,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Outputs implements controller.Controller interface.
|
||||
func (ctrl *DisksController) Outputs() []controller.Output {
|
||||
return []controller.Output{
|
||||
{
|
||||
Type: block.DiskType,
|
||||
Kind: controller.OutputExclusive,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Run implements controller.Controller interface.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func (ctrl *DisksController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) error {
|
||||
// lastObservedGenerations holds the last observed generation of each device.
|
||||
//
|
||||
// when the generation of a device changes, the device might have changed and might need to be re-probed.
|
||||
lastObservedGenerations := map[string]int{}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-r.EventCh():
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
|
||||
blockdevices, err := safe.ReaderListAll[*block.Device](ctx, r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list block devices: %w", err)
|
||||
}
|
||||
|
||||
touchedDisks := map[string]struct{}{}
|
||||
|
||||
for iter := blockdevices.Iterator(); iter.Next(); {
|
||||
device := iter.Value()
|
||||
|
||||
if device.TypedSpec().Type != "disk" {
|
||||
continue
|
||||
}
|
||||
|
||||
if lastObserved, ok := lastObservedGenerations[device.Metadata().ID()]; ok && device.TypedSpec().Generation == lastObserved {
|
||||
// ignore disks which have some generation as before (don't query them once again)
|
||||
touchedDisks[device.Metadata().ID()] = struct{}{}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
lastObservedGenerations[device.Metadata().ID()] = device.TypedSpec().Generation
|
||||
|
||||
if err = ctrl.analyzeBlockDevice(ctx, r, logger.With(zap.String("device", device.Metadata().ID())), device, touchedDisks); err != nil {
|
||||
return fmt.Errorf("failed to analyze block device: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
disks, err := safe.ReaderListAll[*block.Disk](ctx, r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list disks: %w", err)
|
||||
}
|
||||
|
||||
for iter := disks.Iterator(); iter.Next(); {
|
||||
disk := iter.Value()
|
||||
|
||||
if _, ok := touchedDisks[disk.Metadata().ID()]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if err = r.Destroy(ctx, disk.Metadata()); err != nil {
|
||||
return fmt.Errorf("failed to remove disk: %w", err)
|
||||
}
|
||||
|
||||
delete(lastObservedGenerations, disk.Metadata().ID())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctrl *DisksController) analyzeBlockDevice(ctx context.Context, r controller.Runtime, logger *zap.Logger, device *block.Device, touchedDisks map[string]struct{}) error {
|
||||
bd, err := blkdev.NewFromPath(filepath.Join("/dev", device.Metadata().ID()))
|
||||
if err != nil {
|
||||
logger.Debug("failed to open blockdevice", zap.Error(err))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
size, err := bd.GetSize()
|
||||
if err != nil || size == 0 {
|
||||
return nil //nolint:nilerr
|
||||
}
|
||||
|
||||
if privateDM, _ := bd.IsPrivateDeviceMapper(); privateDM { //nolint:errcheck
|
||||
return nil
|
||||
}
|
||||
|
||||
ioSize, err := bd.GetIOSize()
|
||||
if err != nil {
|
||||
logger.Debug("failed to get io size", zap.Error(err))
|
||||
}
|
||||
|
||||
sectorSize := bd.GetSectorSize()
|
||||
|
||||
readOnly, err := bd.IsReadOnly()
|
||||
if err != nil {
|
||||
logger.Debug("failed to get read only", zap.Error(err))
|
||||
}
|
||||
|
||||
props, err := bd.GetProperties()
|
||||
if err != nil {
|
||||
logger.Debug("failed to get properties", zap.Error(err))
|
||||
}
|
||||
|
||||
touchedDisks[device.Metadata().ID()] = struct{}{}
|
||||
|
||||
return safe.WriterModify(ctx, r, block.NewDisk(block.NamespaceName, device.Metadata().ID()), func(d *block.Disk) error {
|
||||
d.TypedSpec().Size = size
|
||||
d.TypedSpec().IOSize = ioSize
|
||||
d.TypedSpec().SectorSize = sectorSize
|
||||
d.TypedSpec().Readonly = readOnly
|
||||
|
||||
d.TypedSpec().Model = props.Model
|
||||
d.TypedSpec().Serial = props.Serial
|
||||
d.TypedSpec().Modalias = props.Modalias
|
||||
d.TypedSpec().WWID = props.WWID
|
||||
d.TypedSpec().BusPath = props.BusPath
|
||||
d.TypedSpec().SubSystem = props.SubSystem
|
||||
d.TypedSpec().Transport = props.Transport
|
||||
d.TypedSpec().Rotational = props.Rotational
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
91
internal/app/machined/pkg/controllers/block/system_disk.go
Normal file
91
internal/app/machined/pkg/controllers/block/system_disk.go
Normal file
@ -0,0 +1,91 @@
|
||||
// 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 block
|
||||
|
||||
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/constants"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/block"
|
||||
)
|
||||
|
||||
// SystemDiskController provides a detailed view of blockdevices of type 'disk'.
|
||||
type SystemDiskController struct{}
|
||||
|
||||
// Name implements controller.Controller interface.
|
||||
func (ctrl *SystemDiskController) Name() string {
|
||||
return "block.SystemDiskController"
|
||||
}
|
||||
|
||||
// Inputs implements controller.Controller interface.
|
||||
func (ctrl *SystemDiskController) Inputs() []controller.Input {
|
||||
return []controller.Input{
|
||||
{
|
||||
Namespace: block.NamespaceName,
|
||||
Type: block.DiscoveredVolumeType,
|
||||
Kind: controller.InputWeak,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Outputs implements controller.Controller interface.
|
||||
func (ctrl *SystemDiskController) Outputs() []controller.Output {
|
||||
return []controller.Output{
|
||||
{
|
||||
Type: block.SystemDiskType,
|
||||
Kind: controller.OutputExclusive,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Run implements controller.Controller interface.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func (ctrl *SystemDiskController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) error {
|
||||
for {
|
||||
select {
|
||||
case <-r.EventCh():
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
|
||||
discoveredVolumes, err := safe.ReaderListAll[*block.DiscoveredVolume](ctx, r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list discovered volumes: %w", err)
|
||||
}
|
||||
|
||||
var systemDiskID string
|
||||
|
||||
for iter := discoveredVolumes.Iterator(); iter.Next(); {
|
||||
volume := iter.Value()
|
||||
|
||||
if volume.TypedSpec().PartitionLabel == constants.MetaPartitionLabel {
|
||||
systemDiskID = volume.TypedSpec().Parent
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if systemDiskID != "" {
|
||||
if err = safe.WriterModify(ctx, r, block.NewSystemDisk(block.NamespaceName, block.SystemDiskID), func(d *block.SystemDisk) error {
|
||||
d.TypedSpec().DiskID = systemDiskID
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to write system disk: %w", err)
|
||||
}
|
||||
} else {
|
||||
if err = r.Destroy(ctx, block.NewSystemDisk(block.NamespaceName, block.SystemDiskID).Metadata()); err != nil && !state.IsNotFoundError(err) {
|
||||
return fmt.Errorf("failed to destroy system disk: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,6 +92,8 @@ func (ctrl *Controller) Run(ctx context.Context, drainer *runtime.Drainer) error
|
||||
V1Alpha1Mode: ctrl.v1alpha1Runtime.State().Platform().Mode(),
|
||||
},
|
||||
&block.DiscoveryController{},
|
||||
&block.DisksController{},
|
||||
&block.SystemDiskController{},
|
||||
&cluster.AffiliateMergeController{},
|
||||
cluster.NewConfigController(),
|
||||
&cluster.DiscoveryServiceController{},
|
||||
|
||||
@ -97,6 +97,8 @@ func NewState() (*State, error) {
|
||||
for _, r := range []meta.ResourceWithRD{
|
||||
&block.Device{},
|
||||
&block.DiscoveredVolume{},
|
||||
&block.Disk{},
|
||||
&block.SystemDisk{},
|
||||
&cluster.Affiliate{},
|
||||
&cluster.Config{},
|
||||
&cluster.Identity{},
|
||||
|
||||
@ -7,17 +7,20 @@ package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/siderolabs/gen/xslices"
|
||||
bddisk "github.com/siderolabs/go-blockdevice/blockdevice/util/disk"
|
||||
"github.com/cosi-project/runtime/pkg/safe"
|
||||
"github.com/cosi-project/runtime/pkg/state"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/siderolabs/talos/pkg/machinery/api/storage"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/block"
|
||||
)
|
||||
|
||||
// Server implements storage.StorageService.
|
||||
// TODO: this is not a full blown service yet, it's used as the common base in the machine and the maintenance services.
|
||||
//
|
||||
// It is only kept here for compatibility purposes, proper API is to query `block.Disk` resources.
|
||||
type Server struct {
|
||||
storage.UnimplementedStorageServiceServer
|
||||
Controller runtime.Controller
|
||||
@ -25,32 +28,48 @@ type Server struct {
|
||||
|
||||
// Disks implements storage.StorageService.
|
||||
func (s *Server) Disks(ctx context.Context, in *emptypb.Empty) (reply *storage.DisksResponse, err error) {
|
||||
disks, err := bddisk.List()
|
||||
st := s.Controller.Runtime().State().V1Alpha2().Resources()
|
||||
|
||||
systemDisk, err := safe.StateGetByID[*block.SystemDisk](ctx, st, block.SystemDiskID)
|
||||
if err != nil && !state.IsNotFoundError(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
disks, err := safe.StateListAll[*block.Disk](ctx, st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
systemDisk := s.Controller.Runtime().State().Machine().Disk()
|
||||
diskConv := func(d *block.Disk) (*storage.Disk, error) {
|
||||
var diskType storage.Disk_DiskType
|
||||
|
||||
diskConv := func(d *bddisk.Disk) *storage.Disk {
|
||||
return &storage.Disk{
|
||||
DeviceName: d.DeviceName,
|
||||
Model: d.Model,
|
||||
Size: d.Size,
|
||||
Name: d.Name,
|
||||
Serial: d.Serial,
|
||||
Modalias: d.Modalias,
|
||||
Uuid: d.UUID,
|
||||
Wwid: d.WWID,
|
||||
Type: storage.Disk_DiskType(d.Type),
|
||||
BusPath: d.BusPath,
|
||||
SystemDisk: systemDisk != nil && d.DeviceName == systemDisk.Device().Name(),
|
||||
Subsystem: d.SubSystem,
|
||||
Readonly: d.ReadOnly,
|
||||
switch {
|
||||
case d.TypedSpec().Transport == "nvme":
|
||||
diskType = storage.Disk_NVME
|
||||
case d.TypedSpec().Transport == "mmc":
|
||||
diskType = storage.Disk_SD
|
||||
case d.TypedSpec().Rotational:
|
||||
diskType = storage.Disk_HDD
|
||||
case d.TypedSpec().Transport != "":
|
||||
diskType = storage.Disk_SSD
|
||||
}
|
||||
|
||||
return &storage.Disk{
|
||||
DeviceName: filepath.Join("/dev", d.Metadata().ID()),
|
||||
Model: d.TypedSpec().Model,
|
||||
Size: d.TypedSpec().Size,
|
||||
Serial: d.TypedSpec().Serial,
|
||||
Modalias: d.TypedSpec().Modalias,
|
||||
Wwid: d.TypedSpec().WWID,
|
||||
Type: diskType,
|
||||
BusPath: d.TypedSpec().BusPath,
|
||||
SystemDisk: systemDisk != nil && d.Metadata().ID() == systemDisk.TypedSpec().DiskID,
|
||||
Subsystem: d.TypedSpec().SubSystem,
|
||||
Readonly: d.TypedSpec().Readonly,
|
||||
}, nil
|
||||
}
|
||||
|
||||
diskList := xslices.Map(disks, diskConv)
|
||||
diskList, _ := safe.Map(disks, diskConv) //nolint:errcheck
|
||||
|
||||
reply = &storage.DisksResponse{
|
||||
Messages: []*storage.Disks{
|
||||
|
||||
@ -32,6 +32,10 @@ func (suite *VolumesSuite) SuiteName() string {
|
||||
|
||||
// SetupTest ...
|
||||
func (suite *VolumesSuite) SetupTest() {
|
||||
if !suite.Capabilities().SupportsVolumes {
|
||||
suite.T().Skip("cluster doesn't support volumes")
|
||||
}
|
||||
|
||||
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), time.Minute)
|
||||
}
|
||||
|
||||
@ -44,10 +48,6 @@ func (suite *VolumesSuite) TearDownTest() {
|
||||
|
||||
// TestDiscoveredVolumes verifies that standard Talos partitions are discovered.
|
||||
func (suite *VolumesSuite) TestDiscoveredVolumes() {
|
||||
if !suite.Capabilities().SupportsVolumes {
|
||||
suite.T().Skip("cluster doesn't support volumes")
|
||||
}
|
||||
|
||||
for _, node := range suite.DiscoverNodeInternalIPs(suite.ctx) {
|
||||
suite.Run(node, func() {
|
||||
suite.testDiscoveredVolumes(node)
|
||||
@ -114,6 +114,60 @@ func (suite *VolumesSuite) testDiscoveredVolumes(node string) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestSystemDisk verifies that Talos system disk is discovered.
|
||||
func (suite *VolumesSuite) TestSystemDisk() {
|
||||
for _, node := range suite.DiscoverNodeInternalIPs(suite.ctx) {
|
||||
suite.Run(node, func() {
|
||||
ctx := client.WithNode(suite.ctx, node)
|
||||
|
||||
systemDisk, err := safe.StateGetByID[*block.SystemDisk](ctx, suite.Client.COSI, block.SystemDiskID)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NotEmpty(systemDisk.TypedSpec().DiskID)
|
||||
|
||||
suite.T().Logf("system disk: %s", systemDisk.TypedSpec().DiskID)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestDisks verifies that Talos discovers disks.
|
||||
func (suite *VolumesSuite) TestDisks() {
|
||||
for _, node := range suite.DiscoverNodeInternalIPs(suite.ctx) {
|
||||
suite.Run(node, func() {
|
||||
ctx := client.WithNode(suite.ctx, node)
|
||||
|
||||
disks, err := safe.StateListAll[*block.Disk](ctx, suite.Client.COSI)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// there should be at least two disks - loop0 for Talos squashfs and a system disk
|
||||
suite.Assert().Greater(disks.Len(), 1)
|
||||
|
||||
var diskNames []string
|
||||
|
||||
for iter := disks.Iterator(); iter.Next(); {
|
||||
disk := iter.Value()
|
||||
|
||||
if disk.TypedSpec().Readonly {
|
||||
continue
|
||||
}
|
||||
|
||||
suite.Assert().NotEmpty(disk.TypedSpec().Size, "disk: %s", disk.Metadata().ID())
|
||||
suite.Assert().NotEmpty(disk.TypedSpec().IOSize, "disk: %s", disk.Metadata().ID())
|
||||
suite.Assert().NotEmpty(disk.TypedSpec().SectorSize, "disk: %s", disk.Metadata().ID())
|
||||
|
||||
if suite.Cluster != nil {
|
||||
// running on our own provider, transport should be always detected
|
||||
suite.Assert().NotEmpty(disk.TypedSpec().Transport, "disk: %s", disk.Metadata().ID())
|
||||
}
|
||||
|
||||
diskNames = append(diskNames, disk.Metadata().ID())
|
||||
}
|
||||
|
||||
suite.T().Logf("disks: %v", diskNames)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
allSuites = append(allSuites, new(VolumesSuite))
|
||||
}
|
||||
|
||||
@ -22,6 +22,10 @@ func (suite *DisksSuite) SuiteName() string {
|
||||
|
||||
// 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()})
|
||||
}
|
||||
|
||||
|
||||
@ -293,6 +293,190 @@ func (x *DiscoveredVolumeSpec) GetParent() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// DiskSpec is the spec for Disks status.
|
||||
type DiskSpec struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Size uint64 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"`
|
||||
IoSize uint64 `protobuf:"varint,2,opt,name=io_size,json=ioSize,proto3" json:"io_size,omitempty"`
|
||||
SectorSize uint64 `protobuf:"varint,3,opt,name=sector_size,json=sectorSize,proto3" json:"sector_size,omitempty"`
|
||||
Readonly bool `protobuf:"varint,4,opt,name=readonly,proto3" json:"readonly,omitempty"`
|
||||
Model string `protobuf:"bytes,5,opt,name=model,proto3" json:"model,omitempty"`
|
||||
Serial string `protobuf:"bytes,6,opt,name=serial,proto3" json:"serial,omitempty"`
|
||||
Modalias string `protobuf:"bytes,7,opt,name=modalias,proto3" json:"modalias,omitempty"`
|
||||
Wwid string `protobuf:"bytes,8,opt,name=wwid,proto3" json:"wwid,omitempty"`
|
||||
BusPath string `protobuf:"bytes,9,opt,name=bus_path,json=busPath,proto3" json:"bus_path,omitempty"`
|
||||
SubSystem string `protobuf:"bytes,10,opt,name=sub_system,json=subSystem,proto3" json:"sub_system,omitempty"`
|
||||
Transport string `protobuf:"bytes,11,opt,name=transport,proto3" json:"transport,omitempty"`
|
||||
Rotational bool `protobuf:"varint,12,opt,name=rotational,proto3" json:"rotational,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DiskSpec) Reset() {
|
||||
*x = DiskSpec{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_resource_definitions_block_block_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *DiskSpec) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DiskSpec) ProtoMessage() {}
|
||||
|
||||
func (x *DiskSpec) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_resource_definitions_block_block_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DiskSpec.ProtoReflect.Descriptor instead.
|
||||
func (*DiskSpec) Descriptor() ([]byte, []int) {
|
||||
return file_resource_definitions_block_block_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetSize() uint64 {
|
||||
if x != nil {
|
||||
return x.Size
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetIoSize() uint64 {
|
||||
if x != nil {
|
||||
return x.IoSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetSectorSize() uint64 {
|
||||
if x != nil {
|
||||
return x.SectorSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetReadonly() bool {
|
||||
if x != nil {
|
||||
return x.Readonly
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetModel() string {
|
||||
if x != nil {
|
||||
return x.Model
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetSerial() string {
|
||||
if x != nil {
|
||||
return x.Serial
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetModalias() string {
|
||||
if x != nil {
|
||||
return x.Modalias
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetWwid() string {
|
||||
if x != nil {
|
||||
return x.Wwid
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetBusPath() string {
|
||||
if x != nil {
|
||||
return x.BusPath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetSubSystem() string {
|
||||
if x != nil {
|
||||
return x.SubSystem
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetTransport() string {
|
||||
if x != nil {
|
||||
return x.Transport
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DiskSpec) GetRotational() bool {
|
||||
if x != nil {
|
||||
return x.Rotational
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SystemDiskSpec is the spec for SystemDisks status.
|
||||
type SystemDiskSpec struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
DiskId string `protobuf:"bytes,1,opt,name=disk_id,json=diskId,proto3" json:"disk_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SystemDiskSpec) Reset() {
|
||||
*x = SystemDiskSpec{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_resource_definitions_block_block_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SystemDiskSpec) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SystemDiskSpec) ProtoMessage() {}
|
||||
|
||||
func (x *SystemDiskSpec) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_resource_definitions_block_block_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SystemDiskSpec.ProtoReflect.Descriptor instead.
|
||||
func (*SystemDiskSpec) Descriptor() ([]byte, []int) {
|
||||
return file_resource_definitions_block_block_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *SystemDiskSpec) GetDiskId() string {
|
||||
if x != nil {
|
||||
return x.DiskId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_resource_definitions_block_block_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_resource_definitions_block_block_proto_rawDesc = []byte{
|
||||
@ -348,12 +532,36 @@ var file_resource_definitions_block_block_proto_rawDesc = []byte{
|
||||
0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68,
|
||||
0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x61,
|
||||
0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x10, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x4a, 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,
|
||||
0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x22, 0xca, 0x02, 0x0a, 0x08, 0x44,
|
||||
0x69, 0x73, 0x6b, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69,
|
||||
0x6f, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x69, 0x6f,
|
||||
0x53, 0x69, 0x7a, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x73,
|
||||
0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x73, 0x65, 0x63, 0x74, 0x6f,
|
||||
0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c,
|
||||
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c,
|
||||
0x79, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61,
|
||||
0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12,
|
||||
0x1a, 0x0a, 0x08, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x77,
|
||||
0x77, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x77, 0x77, 0x69, 0x64, 0x12,
|
||||
0x19, 0x0a, 0x08, 0x62, 0x75, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x07, 0x62, 0x75, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75,
|
||||
0x62, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x73, 0x75, 0x62, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x61,
|
||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x6f, 0x74, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x6f, 0x74,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x29, 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, 0x42, 0x4a, 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 (
|
||||
@ -368,10 +576,12 @@ func file_resource_definitions_block_block_proto_rawDescGZIP() []byte {
|
||||
return file_resource_definitions_block_block_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_resource_definitions_block_block_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_resource_definitions_block_block_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_resource_definitions_block_block_proto_goTypes = []interface{}{
|
||||
(*DeviceSpec)(nil), // 0: talos.resource.definitions.block.DeviceSpec
|
||||
(*DiscoveredVolumeSpec)(nil), // 1: talos.resource.definitions.block.DiscoveredVolumeSpec
|
||||
(*DiskSpec)(nil), // 2: talos.resource.definitions.block.DiskSpec
|
||||
(*SystemDiskSpec)(nil), // 3: talos.resource.definitions.block.SystemDiskSpec
|
||||
}
|
||||
var file_resource_definitions_block_block_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
@ -411,6 +621,30 @@ func file_resource_definitions_block_block_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_resource_definitions_block_block_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*DiskSpec); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_resource_definitions_block_block_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SystemDiskSpec); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
@ -418,7 +652,7 @@ func file_resource_definitions_block_block_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_resource_definitions_block_block_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@ -233,6 +233,163 @@ func (m *DiscoveredVolumeSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error)
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *DiskSpec) 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 *DiskSpec) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *DiskSpec) 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.Rotational {
|
||||
i--
|
||||
if m.Rotational {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x60
|
||||
}
|
||||
if len(m.Transport) > 0 {
|
||||
i -= len(m.Transport)
|
||||
copy(dAtA[i:], m.Transport)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Transport)))
|
||||
i--
|
||||
dAtA[i] = 0x5a
|
||||
}
|
||||
if len(m.SubSystem) > 0 {
|
||||
i -= len(m.SubSystem)
|
||||
copy(dAtA[i:], m.SubSystem)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SubSystem)))
|
||||
i--
|
||||
dAtA[i] = 0x52
|
||||
}
|
||||
if len(m.BusPath) > 0 {
|
||||
i -= len(m.BusPath)
|
||||
copy(dAtA[i:], m.BusPath)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.BusPath)))
|
||||
i--
|
||||
dAtA[i] = 0x4a
|
||||
}
|
||||
if len(m.Wwid) > 0 {
|
||||
i -= len(m.Wwid)
|
||||
copy(dAtA[i:], m.Wwid)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Wwid)))
|
||||
i--
|
||||
dAtA[i] = 0x42
|
||||
}
|
||||
if len(m.Modalias) > 0 {
|
||||
i -= len(m.Modalias)
|
||||
copy(dAtA[i:], m.Modalias)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Modalias)))
|
||||
i--
|
||||
dAtA[i] = 0x3a
|
||||
}
|
||||
if len(m.Serial) > 0 {
|
||||
i -= len(m.Serial)
|
||||
copy(dAtA[i:], m.Serial)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Serial)))
|
||||
i--
|
||||
dAtA[i] = 0x32
|
||||
}
|
||||
if len(m.Model) > 0 {
|
||||
i -= len(m.Model)
|
||||
copy(dAtA[i:], m.Model)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Model)))
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
}
|
||||
if m.Readonly {
|
||||
i--
|
||||
if m.Readonly {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x20
|
||||
}
|
||||
if m.SectorSize != 0 {
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(m.SectorSize))
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
if m.IoSize != 0 {
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(m.IoSize))
|
||||
i--
|
||||
dAtA[i] = 0x10
|
||||
}
|
||||
if m.Size != 0 {
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Size))
|
||||
i--
|
||||
dAtA[i] = 0x8
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *SystemDiskSpec) 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 *SystemDiskSpec) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *SystemDiskSpec) 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.DiskId) > 0 {
|
||||
i -= len(m.DiskId)
|
||||
copy(dAtA[i:], m.DiskId)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.DiskId)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *DeviceSpec) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@ -338,6 +495,73 @@ func (m *DiscoveredVolumeSpec) SizeVT() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *DiskSpec) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.Size != 0 {
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(m.Size))
|
||||
}
|
||||
if m.IoSize != 0 {
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(m.IoSize))
|
||||
}
|
||||
if m.SectorSize != 0 {
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(m.SectorSize))
|
||||
}
|
||||
if m.Readonly {
|
||||
n += 2
|
||||
}
|
||||
l = len(m.Model)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.Serial)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.Modalias)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.Wwid)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.BusPath)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.SubSystem)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.Transport)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
if m.Rotational {
|
||||
n += 2
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *SystemDiskSpec) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.DiskId)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *DeviceSpec) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
@ -1065,3 +1289,458 @@ func (m *DiscoveredVolumeSpec) UnmarshalVT(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *DiskSpec) 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: DiskSpec: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: DiskSpec: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Size", wireType)
|
||||
}
|
||||
m.Size = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Size |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field IoSize", wireType)
|
||||
}
|
||||
m.IoSize = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.IoSize |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SectorSize", wireType)
|
||||
}
|
||||
m.SectorSize = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.SectorSize |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Readonly", 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.Readonly = bool(v != 0)
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Model", 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.Model = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Serial", 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.Serial = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 7:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Modalias", 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.Modalias = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Wwid", 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.Wwid = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 9:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field BusPath", 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.BusPath = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 10:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SubSystem", 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.SubSystem = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 11:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Transport", 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.Transport = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 12:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Rotational", 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.Rotational = 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 *SystemDiskSpec) 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: SystemDiskSpec: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: SystemDiskSpec: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field DiskId", 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.DiskId = string(dAtA[iNdEx:postIndex])
|
||||
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
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/v1alpha1"
|
||||
)
|
||||
|
||||
//go:generate deep-copy -type DeviceSpec -type DiscoveredVolumeSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go .
|
||||
//go:generate deep-copy -type DeviceSpec -type DiscoveredVolumeSpec -type DiskSpec -type SystemDiskSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go .
|
||||
|
||||
// NamespaceName contains configuration resources.
|
||||
const NamespaceName resource.Namespace = v1alpha1.NamespaceName
|
||||
|
||||
@ -27,6 +27,8 @@ func TestRegisterResource(t *testing.T) {
|
||||
for _, resource := range []meta.ResourceWithRD{
|
||||
&block.Device{},
|
||||
&block.DiscoveredVolume{},
|
||||
&block.Disk{},
|
||||
&block.SystemDisk{},
|
||||
} {
|
||||
assert.NoError(t, resourceRegistry.Register(ctx, resource))
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// 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/.
|
||||
|
||||
// Code generated by "deep-copy -type DeviceSpec -type DiscoveredVolumeSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go ."; DO NOT EDIT.
|
||||
// Code generated by "deep-copy -type DeviceSpec -type DiscoveredVolumeSpec -type DiskSpec -type SystemDiskSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go ."; DO NOT EDIT.
|
||||
|
||||
package block
|
||||
|
||||
@ -17,3 +17,15 @@ func (o DiscoveredVolumeSpec) DeepCopy() DiscoveredVolumeSpec {
|
||||
var cp DiscoveredVolumeSpec = o
|
||||
return cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of DiskSpec.
|
||||
func (o DiskSpec) DeepCopy() DiskSpec {
|
||||
var cp DiskSpec = o
|
||||
return cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of SystemDiskSpec.
|
||||
func (o SystemDiskSpec) DeepCopy() SystemDiskSpec {
|
||||
var cp SystemDiskSpec = o
|
||||
return cp
|
||||
}
|
||||
|
||||
99
pkg/machinery/resources/block/disk.go
Normal file
99
pkg/machinery/resources/block/disk.go
Normal file
@ -0,0 +1,99 @@
|
||||
// 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 block
|
||||
|
||||
import (
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/resource/meta"
|
||||
"github.com/cosi-project/runtime/pkg/resource/protobuf"
|
||||
"github.com/cosi-project/runtime/pkg/resource/typed"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/proto"
|
||||
)
|
||||
|
||||
// DiskType is type of Disk resource.
|
||||
const DiskType = resource.Type("Disks.block.talos.dev")
|
||||
|
||||
// Disk resource holds status of hardware disks.
|
||||
type Disk = typed.Resource[DiskSpec, DiskExtension]
|
||||
|
||||
// DiskSpec is the spec for Disks status.
|
||||
//
|
||||
//gotagsrewrite:gen
|
||||
type DiskSpec struct {
|
||||
Size uint64 `yaml:"size" protobuf:"1"`
|
||||
IOSize uint `yaml:"ioSize" protobuf:"2"`
|
||||
SectorSize uint `yaml:"sectorSize" protobuf:"3"`
|
||||
|
||||
Readonly bool `yaml:"readonly" protobuf:"4"`
|
||||
|
||||
Model string `yaml:"model,omitempty" protobuf:"5"`
|
||||
Serial string `yaml:"serial,omitempty" protobuf:"6"`
|
||||
Modalias string `yaml:"modalias,omitempty" protobuf:"7"`
|
||||
WWID string `yaml:"wwid,omitempty" protobuf:"8"`
|
||||
BusPath string `yaml:"busPath,omitempty" protobuf:"9"`
|
||||
SubSystem string `yaml:"subSystem,omitempty" protobuf:"10"`
|
||||
Transport string `yaml:"transport,omitempty" protobuf:"11"`
|
||||
Rotational bool `yaml:"rotational,omitempty" protobuf:"12"`
|
||||
}
|
||||
|
||||
// NewDisk initializes a BlockDisk resource.
|
||||
func NewDisk(namespace resource.Namespace, id resource.ID) *Disk {
|
||||
return typed.NewResource[DiskSpec, DiskExtension](
|
||||
resource.NewMetadata(namespace, DiskType, id, resource.VersionUndefined),
|
||||
DiskSpec{},
|
||||
)
|
||||
}
|
||||
|
||||
// DiskExtension is auxiliary resource data for BlockDisk.
|
||||
type DiskExtension struct{}
|
||||
|
||||
// ResourceDefinition implements meta.ResourceDefinitionProvider interface.
|
||||
func (DiskExtension) ResourceDefinition() meta.ResourceDefinitionSpec {
|
||||
return meta.ResourceDefinitionSpec{
|
||||
Type: DiskType,
|
||||
Aliases: []resource.Type{},
|
||||
DefaultNamespace: NamespaceName,
|
||||
PrintColumns: []meta.PrintColumn{
|
||||
{
|
||||
Name: "Size",
|
||||
JSONPath: `{.size}`,
|
||||
},
|
||||
{
|
||||
Name: "Read Only",
|
||||
JSONPath: `{.readonly}`,
|
||||
},
|
||||
{
|
||||
Name: "Transport",
|
||||
JSONPath: `{.transport}`,
|
||||
},
|
||||
{
|
||||
Name: "Rotational",
|
||||
JSONPath: `{.rotational}`,
|
||||
},
|
||||
{
|
||||
Name: "WWID",
|
||||
JSONPath: `{.wwid}`,
|
||||
},
|
||||
{
|
||||
Name: "Model",
|
||||
JSONPath: `{.model}`,
|
||||
},
|
||||
{
|
||||
Name: "Serial",
|
||||
JSONPath: `{.serial}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterDefaultTypes()
|
||||
|
||||
err := protobuf.RegisterDynamic[DiskSpec](DiskType, &Disk{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
65
pkg/machinery/resources/block/system_disk.go
Normal file
65
pkg/machinery/resources/block/system_disk.go
Normal file
@ -0,0 +1,65 @@
|
||||
// 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 block
|
||||
|
||||
import (
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/resource/meta"
|
||||
"github.com/cosi-project/runtime/pkg/resource/protobuf"
|
||||
"github.com/cosi-project/runtime/pkg/resource/typed"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/proto"
|
||||
)
|
||||
|
||||
// SystemDiskType is type of SystemDisk resource.
|
||||
const SystemDiskType = resource.Type("SystemDisks.block.talos.dev")
|
||||
|
||||
// SystemDisk resource holds ID of the disk which is the Talos system disk.
|
||||
type SystemDisk = typed.Resource[SystemDiskSpec, SystemDiskExtension]
|
||||
|
||||
// SystemDiskID is the singleton resource ID.
|
||||
const SystemDiskID resource.ID = "system-disk"
|
||||
|
||||
// SystemDiskSpec is the spec for SystemDisks status.
|
||||
//
|
||||
//gotagsrewrite:gen
|
||||
type SystemDiskSpec struct {
|
||||
DiskID string `yaml:"diskID" protobuf:"1"`
|
||||
}
|
||||
|
||||
// NewSystemDisk initializes a BlockSystemDisk resource.
|
||||
func NewSystemDisk(namespace resource.Namespace, id resource.ID) *SystemDisk {
|
||||
return typed.NewResource[SystemDiskSpec, SystemDiskExtension](
|
||||
resource.NewMetadata(namespace, SystemDiskType, id, resource.VersionUndefined),
|
||||
SystemDiskSpec{},
|
||||
)
|
||||
}
|
||||
|
||||
// SystemDiskExtension is auxiliary resource data for BlockSystemDisk.
|
||||
type SystemDiskExtension struct{}
|
||||
|
||||
// ResourceDefinition implements meta.ResourceDefinitionProvider interface.
|
||||
func (SystemDiskExtension) ResourceDefinition() meta.ResourceDefinitionSpec {
|
||||
return meta.ResourceDefinitionSpec{
|
||||
Type: SystemDiskType,
|
||||
Aliases: []resource.Type{},
|
||||
DefaultNamespace: NamespaceName,
|
||||
PrintColumns: []meta.PrintColumn{
|
||||
{
|
||||
Name: "Disk",
|
||||
JSONPath: `{.diskID}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterDefaultTypes()
|
||||
|
||||
err := protobuf.RegisterDynamic[SystemDiskSpec](SystemDiskType, &SystemDisk{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@ -40,6 +40,7 @@ type LaunchConfig struct {
|
||||
|
||||
// VM options
|
||||
DiskPaths []string
|
||||
DiskDrivers []string
|
||||
VCPUCount int64
|
||||
MemSize int64
|
||||
QemuExecutable string
|
||||
@ -327,26 +328,65 @@ func launchVM(config *LaunchConfig) error {
|
||||
"-no-reboot",
|
||||
"-boot", fmt.Sprintf("order=%s,reboot-timeout=5000", bootOrder),
|
||||
"-smbios", fmt.Sprintf("type=1,uuid=%s", config.NodeUUID),
|
||||
"-chardev",
|
||||
fmt.Sprintf("socket,path=%s/%s.sock,server=on,wait=off,id=qga0", config.StatePath, config.Hostname),
|
||||
"-device",
|
||||
"virtio-serial",
|
||||
"-device",
|
||||
"virtserialport,chardev=qga0,name=org.qemu.guest_agent.0",
|
||||
"-device",
|
||||
"i6300esb,id=watchdog0",
|
||||
"-chardev", fmt.Sprintf("socket,path=%s/%s.sock,server=on,wait=off,id=qga0", config.StatePath, config.Hostname),
|
||||
"-device", "virtio-serial",
|
||||
"-device", "virtserialport,chardev=qga0,name=org.qemu.guest_agent.0",
|
||||
"-device", "i6300esb,id=watchdog0",
|
||||
"-watchdog-action",
|
||||
"pause",
|
||||
}
|
||||
|
||||
var (
|
||||
scsiAttached, ahciAttached, nvmeAttached bool
|
||||
ahciBus int
|
||||
)
|
||||
|
||||
for i, disk := range config.DiskPaths {
|
||||
driver := "virtio"
|
||||
driver := config.DiskDrivers[i]
|
||||
|
||||
if i > 0 {
|
||||
driver = "ide"
|
||||
switch driver {
|
||||
case "virtio":
|
||||
args = append(args, "-drive", fmt.Sprintf("format=raw,if=virtio,file=%s,cache=none,", disk))
|
||||
case "ide":
|
||||
args = append(args, "-drive", fmt.Sprintf("format=raw,if=ide,file=%s,cache=none,", disk))
|
||||
case "ahci":
|
||||
if !ahciAttached {
|
||||
args = append(args, "-device", "ahci,id=ahci0")
|
||||
ahciAttached = true
|
||||
}
|
||||
|
||||
args = append(args,
|
||||
"-drive", fmt.Sprintf("id=ide%d,format=raw,if=none,file=%s", i, disk),
|
||||
"-device", fmt.Sprintf("ide-hd,drive=ide%d,bus=ahci0.%d", i, ahciBus),
|
||||
)
|
||||
|
||||
ahciBus++
|
||||
case "scsi":
|
||||
if !scsiAttached {
|
||||
args = append(args, "-device", "virtio-scsi-pci,id=scsi0")
|
||||
scsiAttached = true
|
||||
}
|
||||
|
||||
args = append(args,
|
||||
"-drive", fmt.Sprintf("id=scsi%d,format=raw,if=none,file=%s,discard=unmap,aio=native,cache=none", i, disk),
|
||||
"-device", fmt.Sprintf("scsi-hd,drive=scsi%d,bus=scsi0.0", i),
|
||||
)
|
||||
case "nvme":
|
||||
if !nvmeAttached {
|
||||
// [TODO]: once Talos is fixed, use multipath NVME: https://qemu-project.gitlab.io/qemu/system/devices/nvme.html
|
||||
args = append(args,
|
||||
"-device", "nvme,id=nvme-ctrl-0,serial=deadbeef",
|
||||
)
|
||||
nvmeAttached = true
|
||||
}
|
||||
|
||||
args = append(args,
|
||||
"-drive", fmt.Sprintf("id=nvme%d,format=raw,if=none,file=%s,discard=unmap,aio=native,cache=none", i, disk),
|
||||
"-device", fmt.Sprintf("nvme-ns,drive=nvme%d", i),
|
||||
)
|
||||
default:
|
||||
return fmt.Errorf("unsupported disk driver %q", driver)
|
||||
}
|
||||
|
||||
args = append(args, "-drive", fmt.Sprintf("format=raw,if=%s,file=%s,cache=unsafe", driver, disk))
|
||||
}
|
||||
|
||||
machineArg := config.MachineType
|
||||
|
||||
@ -19,6 +19,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/siderolabs/gen/xslices"
|
||||
"github.com/siderolabs/go-procfs/procfs"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
@ -114,9 +115,25 @@ func (p *provisioner) createNode(state *vm.State, clusterReq provision.ClusterRe
|
||||
defaultBootOrder = nodeReq.DefaultBootOrder
|
||||
}
|
||||
|
||||
// backwards compatibility, set Driver if not set
|
||||
for i := range nodeReq.Disks {
|
||||
if nodeReq.Disks[i].Driver != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
nodeReq.Disks[i].Driver = "virtio"
|
||||
} else {
|
||||
nodeReq.Disks[i].Driver = "ide"
|
||||
}
|
||||
}
|
||||
|
||||
launchConfig := LaunchConfig{
|
||||
QemuExecutable: arch.QemuExecutable(),
|
||||
DiskPaths: diskPaths,
|
||||
QemuExecutable: arch.QemuExecutable(),
|
||||
DiskPaths: diskPaths,
|
||||
DiskDrivers: xslices.Map(nodeReq.Disks, func(disk *provision.Disk) string {
|
||||
return disk.Driver
|
||||
}),
|
||||
VCPUCount: vcpuCount,
|
||||
MemSize: memSize,
|
||||
KernelArgs: cmdline.String(),
|
||||
|
||||
@ -158,6 +158,10 @@ type Disk struct {
|
||||
SkipPreallocate bool
|
||||
// Partitions represents the list of partitions.
|
||||
Partitions []*v1alpha1.DiskPartition
|
||||
// Driver for the disk.
|
||||
//
|
||||
// Supported types: "virtio", "ide", "ahci", "scsi", "nvme".
|
||||
Driver string
|
||||
}
|
||||
|
||||
// NodeRequest describes a request for a node.
|
||||
|
||||
@ -29,6 +29,8 @@ description: Talos gRPC API reference.
|
||||
- [resource/definitions/block/block.proto](#resource/definitions/block/block.proto)
|
||||
- [DeviceSpec](#talos.resource.definitions.block.DeviceSpec)
|
||||
- [DiscoveredVolumeSpec](#talos.resource.definitions.block.DiscoveredVolumeSpec)
|
||||
- [DiskSpec](#talos.resource.definitions.block.DiskSpec)
|
||||
- [SystemDiskSpec](#talos.resource.definitions.block.SystemDiskSpec)
|
||||
|
||||
- [resource/definitions/cluster/cluster.proto](#resource/definitions/cluster/cluster.proto)
|
||||
- [AffiliateSpec](#talos.resource.definitions.cluster.AffiliateSpec)
|
||||
@ -813,6 +815,47 @@ DiscoveredVolumeSpec is the spec for DiscoveredVolumes status.
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="talos.resource.definitions.block.DiskSpec"></a>
|
||||
|
||||
### DiskSpec
|
||||
DiskSpec is the spec for Disks status.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| size | [uint64](#uint64) | | |
|
||||
| io_size | [uint64](#uint64) | | |
|
||||
| sector_size | [uint64](#uint64) | | |
|
||||
| readonly | [bool](#bool) | | |
|
||||
| model | [string](#string) | | |
|
||||
| serial | [string](#string) | | |
|
||||
| modalias | [string](#string) | | |
|
||||
| wwid | [string](#string) | | |
|
||||
| bus_path | [string](#string) | | |
|
||||
| sub_system | [string](#string) | | |
|
||||
| transport | [string](#string) | | |
|
||||
| rotational | [bool](#bool) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="talos.resource.definitions.block.SystemDiskSpec"></a>
|
||||
|
||||
### SystemDiskSpec
|
||||
SystemDiskSpec is the spec for SystemDisks status.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| disk_id | [string](#string) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
<!-- end enums -->
|
||||
|
||||
@ -122,6 +122,7 @@ talosctl cluster create [flags]
|
||||
-p, --exposed-ports string Comma-separated list of ports/protocols to expose on init node. Ex -p <hostPort>:<containerPort>/<protocol (tcp or udp)> (Docker provisioner only)
|
||||
--extra-boot-kernel-args string add extra kernel args to the initial boot from vmlinuz and initramfs (QEMU only)
|
||||
--extra-disks int number of extra disks to create for each worker VM
|
||||
--extra-disks-drivers strings driver for each extra disk (virtio, ide, ahci, scsi, nvme)
|
||||
--extra-disks-size int default limit on disk size in MB (each VM) (default 5120)
|
||||
--extra-uefi-search-paths strings additional search paths for UEFI firmware (only applies when UEFI is enabled)
|
||||
-h, --help help for create
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user