From c30125d4be8fdb3a51e90cc76de470dc47a8ec6c Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Tue, 5 Nov 2024 10:44:02 +0800 Subject: [PATCH] feat(region,host,host-deployer,climc): support ext4 casefold feature disk (#21502) --- pkg/apis/compute/api.go | 3 + pkg/apis/compute/disk.go | 28 + pkg/apis/container.go | 2 + pkg/apis/host/container.go | 1 + pkg/cloudcommon/cmdline/parser.go | 17 + .../container_drivers/volume_mount/disk.go | 28 + pkg/compute/models/containers.go | 1 + pkg/compute/models/disks.go | 18 +- pkg/compute/models/storages.go | 4 +- pkg/hostman/container/volume_mount/disk.go | 20 +- .../diskutils/deploy_iface/deployer.go | 2 +- pkg/hostman/diskutils/fsutils/fsutils.go | 12 +- pkg/hostman/diskutils/libguestfs/driver.go | 4 +- pkg/hostman/diskutils/nbd/driver.go | 4 +- pkg/hostman/diskutils/qemu_kvm/driver.go | 2 +- .../diskutils/qemu_kvm/local_driver.go | 4 +- pkg/hostman/guestfs/kvmpart/kvmpart.go | 2 +- .../guestman/guest_create_from_remote.go | 2 +- pkg/hostman/hostdeployer/apis/deploy.pb.go | 484 +++++++++++------- pkg/hostman/hostdeployer/apis/deploy.proto | 9 + .../hostdeployer/apis/deploy_grpc.pb.go | 1 - pkg/hostman/storageman/disk_base.go | 27 +- pkg/hostman/storageman/disk_local.go | 5 +- pkg/hostman/storageman/disk_lvm.go | 7 +- pkg/hostman/storageman/disk_nvme.go | 6 +- pkg/hostman/storageman/disk_rbd.go | 4 +- pkg/hostman/storageman/disk_slvm.go | 9 +- pkg/hostman/storageman/storage_base.go | 6 +- pkg/hostman/storageman/storage_local.go | 2 +- pkg/hostman/storageman/storage_lvm.go | 2 +- pkg/mcclient/options/compute/containers.go | 6 +- pkg/mcclient/options/compute/servers.go | 1 + 32 files changed, 502 insertions(+), 221 deletions(-) diff --git a/pkg/apis/compute/api.go b/pkg/apis/compute/api.go index dfc362006f..1bb133a481 100644 --- a/pkg/apis/compute/api.go +++ b/pkg/apis/compute/api.go @@ -175,6 +175,9 @@ type DiskConfig struct { // requried: false Fs string `json:"fs"` + // 文件系统特性 + FsFeatures *DiskFsFeatures `json:"fs_features"` + // 磁盘存储格式 // enum: ["qcow2", "raw", "docker", "iso", "vmdk", "vmdkflatver1", "vmdkflatver2", "vmdkflat", "vmdksparse", "vmdksparsever1", "vmdksparsever2", "vmdksepsparse", "vhd"] // requried: false diff --git a/pkg/apis/compute/disk.go b/pkg/apis/compute/disk.go index 55064aef4c..19bad37ea0 100644 --- a/pkg/apis/compute/disk.go +++ b/pkg/apis/compute/disk.go @@ -15,10 +15,12 @@ package compute import ( + "reflect" "time" "yunion.io/x/cloudmux/pkg/multicloud/esxi/vcenter" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/gotypes" "yunion.io/x/pkg/util/fileutils" "yunion.io/x/onecloud/pkg/apis" @@ -26,6 +28,12 @@ import ( "yunion.io/x/onecloud/pkg/httperrors" ) +func init() { + gotypes.RegisterSerializable(reflect.TypeOf(new(DiskFsFeatures)), func() gotypes.ISerializable { + return new(DiskFsFeatures) + }) +} + type DiskCreateInput struct { apis.VirtualResourceCreateInput apis.EncryptedResourceCreateInput @@ -286,6 +294,7 @@ type DiskAllocateInput struct { ImageId string ImageFormat string FsFormat string + FsFeatures *DiskFsFeatures Rebuild bool BackingDiskId string SnapshotId string @@ -340,3 +349,22 @@ type DiskRebuildInput struct { BackupId *string `json:"backup_id,allowempty"` TemplateId *string `json:"template_id,allowempty"` } + +type DiskFsExt4Features struct { + CaseInsensitive bool `json:"case_insensitive"` +} + +type DiskFsFeatures struct { + Ext4 *DiskFsExt4Features `json:"ext4"` +} + +func (d *DiskFsFeatures) String() string { + return jsonutils.Marshal(d).String() +} + +func (d *DiskFsFeatures) IsZero() bool { + if reflect.DeepEqual(*d, DiskFsFeatures{}) { + return true + } + return false +} diff --git a/pkg/apis/container.go b/pkg/apis/container.go index d6245c4b95..643501d1b5 100644 --- a/pkg/apis/container.go +++ b/pkg/apis/container.go @@ -232,6 +232,8 @@ type ContainerVolumeMountDisk struct { SubDirectory string `json:"sub_directory"` StorageSizeFile string `json:"storage_size_file"` Overlay *ContainerVolumeMountDiskOverlay `json:"overlay"` + // case insensitive feature is incompatible with overlayfs + CaseInsensitive bool `json:"case_insensitive"` } type ContainerVolumeMountHostPathType string diff --git a/pkg/apis/host/container.go b/pkg/apis/host/container.go index 1384f526c0..2810072135 100644 --- a/pkg/apis/host/container.go +++ b/pkg/apis/host/container.go @@ -27,6 +27,7 @@ type ContainerVolumeMountDisk struct { SubDirectory string `json:"sub_directory"` StorageSizeFile string `json:"storage_size_file"` Overlay *apis.ContainerVolumeMountDiskOverlay `json:"overlay"` + CaseInsensitive bool `json:"case_insensitive"` } type ContainerVolumeMountCephFS struct { diff --git a/pkg/cloudcommon/cmdline/parser.go b/pkg/cloudcommon/cmdline/parser.go index 17e884bc5e..594ca6b9ee 100644 --- a/pkg/cloudcommon/cmdline/parser.go +++ b/pkg/cloudcommon/cmdline/parser.go @@ -148,6 +148,23 @@ func ParseDiskConfig(diskStr string, idx int) (*compute.DiskConfig, error) { return nil, errors.Errorf("invalid disk fs %s, allow choices: %s", str, osprofile.FS_TYPES) } diskConfig.Fs = str + case "fs_features": + if diskConfig.Fs == "" { + return nil, errors.Errorf("disk fs is required") + } + diskConfig.FsFeatures = &compute.DiskFsFeatures{} + for _, feature := range strings.Split(str, ",") { + if diskConfig.Fs == "ext4" { + if diskConfig.FsFeatures.Ext4 == nil { + diskConfig.FsFeatures.Ext4 = &compute.DiskFsExt4Features{} + } + if feature == "casefold" { + diskConfig.FsFeatures.Ext4.CaseInsensitive = true + } else { + return nil, errors.Errorf("invalid feature %s of %s", feature, diskConfig.Fs) + } + } + } case "format": if !utils.IsInStringArray(str, osprofile.IMAGE_FORMAT_TYPES) { return nil, errors.Errorf("invalid disk format %s, allow choices: %s", str, osprofile.IMAGE_FORMAT_TYPES) diff --git a/pkg/compute/container_drivers/volume_mount/disk.go b/pkg/compute/container_drivers/volume_mount/disk.go index eb2dfa245e..f28787c0a5 100644 --- a/pkg/compute/container_drivers/volume_mount/disk.go +++ b/pkg/compute/container_drivers/volume_mount/disk.go @@ -68,6 +68,28 @@ func (d disk) validateCreateData(ctx context.Context, userCred mcclient.TokenCre return vm, nil } +func (d disk) validateCaseInsensitive(disk *models.SDisk, vm *apis.ContainerVolumeMountDisk) error { + if !vm.CaseInsensitive { + return nil + } + if disk.FsFeatures == nil { + return httperrors.NewInputParameterError("disk(%s) fs_features is not set", disk.GetId()) + } + if disk.FsFeatures.Ext4 == nil { + return httperrors.NewInputParameterError("disk(%s) fs_features.ext4 is not set", disk.GetId()) + } + if !disk.FsFeatures.Ext4.CaseInsensitive { + return httperrors.NewInputParameterError("disk(%s) fs_features.ext4.case_insensitive is not set", disk.GetId()) + } + if vm.Overlay != nil { + return httperrors.NewInputParameterError("can't use case_insensitive and overlay at the same time") + } + if vm.SubDirectory == "" { + return httperrors.NewInputParameterError("sub_directory must set to use case_insensitive") + } + return nil +} + func (d disk) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, pod *models.SGuest, vm *apis.ContainerVolumeMount) (*apis.ContainerVolumeMount, error) { if _, err := d.validateCreateData(ctx, userCred, vm); err != nil { return nil, err @@ -87,6 +109,9 @@ func (d disk) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCre vm.Disk.Id = diskObj.GetId() // remove index vm.Disk.Index = nil + if err := d.validateCaseInsensitive(&diskObj, disk); err != nil { + return nil, err + } } else { if disk.Id == "" { return nil, httperrors.NewNotEmptyError("disk.id is empty") @@ -103,6 +128,9 @@ func (d disk) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCre if !foundDisk { return nil, httperrors.NewNotFoundError("not found pod disk by %s", disk.Id) } + if err := d.validateCaseInsensitive(&diskObj, disk); err != nil { + return nil, err + } } if err := d.validateOverlay(ctx, userCred, vm, &diskObj); err != nil { return nil, errors.Wrapf(err, "validate overlay") diff --git a/pkg/compute/models/containers.go b/pkg/compute/models/containers.go index 678a8a09ea..7f872e93c4 100644 --- a/pkg/compute/models/containers.go +++ b/pkg/compute/models/containers.go @@ -413,6 +413,7 @@ func (vm *ContainerVolumeMountRelation) toHostDiskMount(disk *apis.ContainerVolu SubDirectory: disk.SubDirectory, StorageSizeFile: disk.StorageSizeFile, Overlay: disk.Overlay, + CaseInsensitive: disk.CaseInsensitive, } return ret, nil } diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index 986ea8f074..f56586587e 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -115,6 +115,8 @@ type SDisk struct { // 文件系统 FsFormat string `width:"32" charset:"ascii" nullable:"true" list:"user" json:"fs_format"` + // 文件系统特性 + FsFeatures *api.DiskFsFeatures `length:"medium" nullable:"true" list:"user" json:"fs_features"` // 磁盘类型 // sys: 系统盘 @@ -414,7 +416,9 @@ func (self *SDisk) CustomizeCreate(ctx context.Context, userCred mcclient.TokenC if err := data.Unmarshal(input); err != nil { return errors.Wrap(err, "Unmarshal json") } - self.fetchDiskInfo(input.DiskConfig) + if err := self.fetchDiskInfo(input.DiskConfig); err != nil { + return errors.Wrap(err, "fetch disk info") + } err := self.SEncryptedResource.CustomizeCreate(ctx, userCred, ownerId, data, "disk-"+pinyinutils.Text2Pinyin(self.Name)) if err != nil { return errors.Wrap(err, "SEncryptedResource.CustomizeCreate") @@ -868,6 +872,9 @@ func (self *SDisk) StartAllocate(ctx context.Context, host *SHost, storage *SSto } if len(fsFormat) > 0 { input.FsFormat = fsFormat + if self.FsFeatures != nil { + input.FsFeatures = self.FsFeatures + } } if self.IsEncrypted() { var err error @@ -2220,7 +2227,7 @@ func parseIsoInfo(ctx context.Context, userCred mcclient.TokenCredential, imageI return image, nil } -func (self *SDisk) fetchDiskInfo(diskConfig *api.DiskConfig) { +func (self *SDisk) fetchDiskInfo(diskConfig *api.DiskConfig) error { if len(diskConfig.SnapshotId) > 0 { self.SnapshotId = diskConfig.SnapshotId self.DiskType = diskConfig.DiskType @@ -2241,6 +2248,12 @@ func (self *SDisk) fetchDiskInfo(diskConfig *api.DiskConfig) { if len(diskConfig.Fs) > 0 { self.FsFormat = diskConfig.Fs } + if diskConfig.FsFeatures != nil { + self.FsFeatures = diskConfig.FsFeatures + if self.FsFeatures.Ext4 != nil && self.FsFormat != "ext4" { + return httperrors.NewInputParameterError("only ext4 fs can set fs_features.ext4, current is %q", self.FsFormat) + } + } if self.FsFormat == "swap" { self.DiskType = api.DISK_TYPE_SWAP self.Nonpersistent = true @@ -2260,6 +2273,7 @@ func (self *SDisk) fetchDiskInfo(diskConfig *api.DiskConfig) { self.DiskFormat = diskConfig.Format self.DiskSize = diskConfig.SizeMb self.OsArch = diskConfig.OsArch + return nil } type DiskInfo struct { diff --git a/pkg/compute/models/storages.go b/pkg/compute/models/storages.go index bb5ece1b22..441c1414e9 100644 --- a/pkg/compute/models/storages.go +++ b/pkg/compute/models/storages.go @@ -1454,7 +1454,9 @@ func (self *SStorage) createDisk(ctx context.Context, name string, diskConfig *a disk.SetModelManager(DiskManager, &disk) disk.Name = name - disk.fetchDiskInfo(diskConfig) + if err := disk.fetchDiskInfo(diskConfig); err != nil { + return nil, errors.Wrap(err, "fetchDiskInfo") + } disk.StorageId = self.Id disk.AutoDelete = autoDelete diff --git a/pkg/hostman/container/volume_mount/disk.go b/pkg/hostman/container/volume_mount/disk.go index 343e75ce0b..9229d073a1 100644 --- a/pkg/hostman/container/volume_mount/disk.go +++ b/pkg/hostman/container/volume_mount/disk.go @@ -135,6 +135,14 @@ func (d disk) getOverlayMergedDir(pod IPodInfo, ctrId string, vm *hostapi.Contai return d.getOverlayDir(pod, ctrId, vm, upperDir, "merged") } +func (d disk) setDirCaseInsensitive(dir string) error { + out, err := procutils.NewRemoteCommandAsFarAsPossible("chattr", "+F", dir).Output() + if err != nil { + return errors.Wrapf(err, "enable %q case_insensitive: %s", dir, out) + } + return nil +} + func (d disk) Mount(pod IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount) error { iDisk, gd, err := d.getPodDisk(pod, vm) if err != nil { @@ -160,10 +168,20 @@ func (d disk) Mount(pod IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount } vmDisk := vm.Disk if vmDisk.SubDirectory != "" { - out, err := procutils.NewRemoteCommandAsFarAsPossible("mkdir", "-p", filepath.Join(mntPoint, vmDisk.SubDirectory)).Output() + subDir := filepath.Join(mntPoint, vmDisk.SubDirectory) + out, err := procutils.NewRemoteCommandAsFarAsPossible("mkdir", "-p", subDir).Output() if err != nil { return errors.Wrapf(err, "make sub_directory %s inside %s: %s", vmDisk.SubDirectory, mntPoint, out) } + if vmDisk.CaseInsensitive { + if err := d.setDirCaseInsensitive(subDir); err != nil { + return errors.Wrapf(err, "enable case_insensitive %s", subDir) + } + } + } else { + if vmDisk.CaseInsensitive { + return errors.Errorf("only sub_directory can use case_insensitive") + } } if vmDisk.StorageSizeFile != "" { if err := d.createStorageSizeFile(iDisk, mntPoint, vmDisk); err != nil { diff --git a/pkg/hostman/diskutils/deploy_iface/deployer.go b/pkg/hostman/diskutils/deploy_iface/deployer.go index 6b56ff53c7..75e3e75498 100644 --- a/pkg/hostman/diskutils/deploy_iface/deployer.go +++ b/pkg/hostman/diskutils/deploy_iface/deployer.go @@ -27,7 +27,7 @@ type IDeployer interface { IsLVMPartition() bool Zerofree() ResizePartition() error - FormatPartition(fs, uuid string) error + FormatPartition(fs, uuid string, features *apis.FsFeatures) error MakePartition(fs string) error MountRootfs(readonly bool) (fsdriver.IRootFsDriver, error) diff --git a/pkg/hostman/diskutils/fsutils/fsutils.go b/pkg/hostman/diskutils/fsutils/fsutils.go index 761efbf302..664840cd8f 100644 --- a/pkg/hostman/diskutils/fsutils/fsutils.go +++ b/pkg/hostman/diskutils/fsutils/fsutils.go @@ -383,7 +383,7 @@ func ext4UsageType(path string) string { return "" } -func FormatPartition(path, fs, uuid string) error { +func FormatPartition(path, fs, uuid string, fsFeatures *apis.FsFeatures) error { var cmd, cmdUuid []string switch { case fs == "swap": @@ -395,7 +395,13 @@ func FormatPartition(path, fs, uuid string) error { cmd = []string{"mkfs.ext3"} cmdUuid = []string{"tune2fs", "-U", uuid} case fs == "ext4": - cmd = []string{"mkfs.ext4", "-O", "^64bit", "-E", "lazy_itable_init=1"} + feature := "^64bit" + if fsFeatures != nil && fsFeatures.Ext4 != nil { + if fsFeatures.Ext4.CaseInsensitive { + feature = fmt.Sprintf("%s,casefold", feature) + } + } + cmd = []string{"mkfs.ext4", "-O", feature, "-E", "lazy_itable_init=1"} /* // see /etc/mke2fs.conf, default inode_ratio is 16384 If this option is is not specified, mke2fs will pick a single default usage type based on the size @@ -558,7 +564,7 @@ func FormatFs(d deploy_iface.IDeployer, req *apis.FormatFsParams) (*apis.Empty, if err != nil { return new(apis.Empty), errors.Wrap(err, "MakePartition") } - err = d.FormatPartition(req.FsFormat, req.Uuid) + err = d.FormatPartition(req.FsFormat, req.Uuid, req.FsFeatures) if err != nil { return new(apis.Empty), errors.Wrap(err, "FormatPartition") } diff --git a/pkg/hostman/diskutils/libguestfs/driver.go b/pkg/hostman/diskutils/libguestfs/driver.go index 337df3ef5a..0b4ee22cac 100644 --- a/pkg/hostman/diskutils/libguestfs/driver.go +++ b/pkg/hostman/diskutils/libguestfs/driver.go @@ -217,8 +217,8 @@ func (d *SLibguestfsDriver) ResizePartition() error { return fsutils.ResizeDiskFs(d.nbddev, 0, false) } -func (d *SLibguestfsDriver) FormatPartition(fs, uuid string) error { - return fsutils.FormatPartition(fmt.Sprintf("%sp1", d.nbddev), fs, uuid) +func (d *SLibguestfsDriver) FormatPartition(fs, uuid string, features *apis.FsFeatures) error { + return fsutils.FormatPartition(fmt.Sprintf("%sp1", d.nbddev), fs, uuid, features) } func (d *SLibguestfsDriver) MakePartition(fsFormat string) error { diff --git a/pkg/hostman/diskutils/nbd/driver.go b/pkg/hostman/diskutils/nbd/driver.go index 94b14df2df..0b92b3197c 100644 --- a/pkg/hostman/diskutils/nbd/driver.go +++ b/pkg/hostman/diskutils/nbd/driver.go @@ -239,8 +239,8 @@ func (d *NBDDriver) MakePartition(fs string) error { return fsutils.Mkpartition(d.nbdDev, fs) } -func (d *NBDDriver) FormatPartition(fs, uuid string) error { - return fsutils.FormatPartition(fmt.Sprintf("%sp1", d.nbdDev), fs, uuid) +func (d *NBDDriver) FormatPartition(fs, uuid string, features *apis.FsFeatures) error { + return fsutils.FormatPartition(fmt.Sprintf("%sp1", d.nbdDev), fs, uuid, features) } func (d *NBDDriver) ResizePartition() error { diff --git a/pkg/hostman/diskutils/qemu_kvm/driver.go b/pkg/hostman/diskutils/qemu_kvm/driver.go index 06ed93e77c..87d1d4ffa3 100644 --- a/pkg/hostman/diskutils/qemu_kvm/driver.go +++ b/pkg/hostman/diskutils/qemu_kvm/driver.go @@ -361,7 +361,7 @@ func (d *QemuKvmDriver) ResizePartition() error { return nil } -func (d *QemuKvmDriver) FormatPartition(fs, uuid string) error { +func (d *QemuKvmDriver) FormatPartition(fs, uuid string, features *apis.FsFeatures) error { return nil } diff --git a/pkg/hostman/diskutils/qemu_kvm/local_driver.go b/pkg/hostman/diskutils/qemu_kvm/local_driver.go index f2184e85ff..6edefbefbc 100644 --- a/pkg/hostman/diskutils/qemu_kvm/local_driver.go +++ b/pkg/hostman/diskutils/qemu_kvm/local_driver.go @@ -96,8 +96,8 @@ func (d *LocalDiskDriver) ResizePartition() error { return fsutils.ResizeDiskFs("/dev/sda", 0, false) } -func (d *LocalDiskDriver) FormatPartition(fs, uuid string) error { - return fsutils.FormatPartition("/dev/sda1", fs, uuid) +func (d *LocalDiskDriver) FormatPartition(fs, uuid string, features *apis.FsFeatures) error { + return fsutils.FormatPartition("/dev/sda1", fs, uuid, features) } func (d *LocalDiskDriver) MakePartition(fs string) error { diff --git a/pkg/hostman/guestfs/kvmpart/kvmpart.go b/pkg/hostman/guestfs/kvmpart/kvmpart.go index 9412cbf5ff..32bf7008d0 100644 --- a/pkg/hostman/guestfs/kvmpart/kvmpart.go +++ b/pkg/hostman/guestfs/kvmpart/kvmpart.go @@ -436,7 +436,7 @@ func (p *SKVMGuestDiskPartition) zerofreeFsInternal(fs string) error { } // make partition uuid := uuids["UUID"] - err = fsutils.FormatPartition(p.partDev, fs, uuid) + err = fsutils.FormatPartition(p.partDev, fs, uuid, nil) if err != nil { return errors.Wrapf(err, "FormatPartition %s %s %s", p.partDev, fs, uuid) } diff --git a/pkg/hostman/guestman/guest_create_from_remote.go b/pkg/hostman/guestman/guest_create_from_remote.go index 85da90ddf3..0153f31165 100644 --- a/pkg/hostman/guestman/guest_create_from_remote.go +++ b/pkg/hostman/guestman/guest_create_from_remote.go @@ -93,7 +93,7 @@ func (m *SGuestManager) GuestCreateFromEsxi( var diskInfo jsonutils.JSONObject diskId := disksDesc[i].DiskId iDisk := storage.CreateDisk(diskId) - diskInfo, err = iDisk.CreateRaw(ctx, 0, "qcow2", "", nil, "", connections.Disks[i].DiskPath) + diskInfo, err = iDisk.CreateRaw(ctx, 0, "qcow2", "", nil, nil, "", connections.Disks[i].DiskPath) if err != nil { err = errors.Wrapf(err, "create disk %s failed", diskId) log.Errorf(err.Error()) diff --git a/pkg/hostman/hostdeployer/apis/deploy.pb.go b/pkg/hostman/hostdeployer/apis/deploy.pb.go index 351d5eec52..c71b6c34e2 100644 --- a/pkg/hostman/hostdeployer/apis/deploy.pb.go +++ b/pkg/hostman/hostdeployer/apis/deploy.pb.go @@ -11,11 +11,10 @@ package apis import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( @@ -1315,20 +1314,115 @@ func (x *ResizeFsParams) GetVddkInfo() *VDDKConInfo { return nil } +type FsExt4Features struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CaseInsensitive bool `protobuf:"varint,1,opt,name=CaseInsensitive,proto3" json:"CaseInsensitive,omitempty"` +} + +func (x *FsExt4Features) Reset() { + *x = FsExt4Features{} + if protoimpl.UnsafeEnabled { + mi := &file_deploy_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FsExt4Features) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FsExt4Features) ProtoMessage() {} + +func (x *FsExt4Features) ProtoReflect() protoreflect.Message { + mi := &file_deploy_proto_msgTypes[13] + 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 FsExt4Features.ProtoReflect.Descriptor instead. +func (*FsExt4Features) Descriptor() ([]byte, []int) { + return file_deploy_proto_rawDescGZIP(), []int{13} +} + +func (x *FsExt4Features) GetCaseInsensitive() bool { + if x != nil { + return x.CaseInsensitive + } + return false +} + +type FsFeatures struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ext4 *FsExt4Features `protobuf:"bytes,1,opt,name=ext4,proto3" json:"ext4,omitempty"` +} + +func (x *FsFeatures) Reset() { + *x = FsFeatures{} + if protoimpl.UnsafeEnabled { + mi := &file_deploy_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FsFeatures) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FsFeatures) ProtoMessage() {} + +func (x *FsFeatures) ProtoReflect() protoreflect.Message { + mi := &file_deploy_proto_msgTypes[14] + 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 FsFeatures.ProtoReflect.Descriptor instead. +func (*FsFeatures) Descriptor() ([]byte, []int) { + return file_deploy_proto_rawDescGZIP(), []int{14} +} + +func (x *FsFeatures) GetExt4() *FsExt4Features { + if x != nil { + return x.Ext4 + } + return nil +} + type FormatFsParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - DiskInfo *DiskInfo `protobuf:"bytes,1,opt,name=disk_info,json=diskInfo,proto3" json:"disk_info,omitempty"` - FsFormat string `protobuf:"bytes,2,opt,name=fs_format,json=fsFormat,proto3" json:"fs_format,omitempty"` - Uuid string `protobuf:"bytes,3,opt,name=uuid,proto3" json:"uuid,omitempty"` + DiskInfo *DiskInfo `protobuf:"bytes,1,opt,name=disk_info,json=diskInfo,proto3" json:"disk_info,omitempty"` + FsFormat string `protobuf:"bytes,2,opt,name=fs_format,json=fsFormat,proto3" json:"fs_format,omitempty"` + Uuid string `protobuf:"bytes,3,opt,name=uuid,proto3" json:"uuid,omitempty"` + FsFeatures *FsFeatures `protobuf:"bytes,4,opt,name=fs_features,json=fsFeatures,proto3" json:"fs_features,omitempty"` } func (x *FormatFsParams) Reset() { *x = FormatFsParams{} if protoimpl.UnsafeEnabled { - mi := &file_deploy_proto_msgTypes[13] + mi := &file_deploy_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1341,7 +1435,7 @@ func (x *FormatFsParams) String() string { func (*FormatFsParams) ProtoMessage() {} func (x *FormatFsParams) ProtoReflect() protoreflect.Message { - mi := &file_deploy_proto_msgTypes[13] + mi := &file_deploy_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1354,7 +1448,7 @@ func (x *FormatFsParams) ProtoReflect() protoreflect.Message { // Deprecated: Use FormatFsParams.ProtoReflect.Descriptor instead. func (*FormatFsParams) Descriptor() ([]byte, []int) { - return file_deploy_proto_rawDescGZIP(), []int{13} + return file_deploy_proto_rawDescGZIP(), []int{15} } func (x *FormatFsParams) GetDiskInfo() *DiskInfo { @@ -1378,6 +1472,13 @@ func (x *FormatFsParams) GetUuid() string { return "" } +func (x *FormatFsParams) GetFsFeatures() *FsFeatures { + if x != nil { + return x.FsFeatures + } + return nil +} + type ReleaseInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1392,7 +1493,7 @@ type ReleaseInfo struct { func (x *ReleaseInfo) Reset() { *x = ReleaseInfo{} if protoimpl.UnsafeEnabled { - mi := &file_deploy_proto_msgTypes[14] + mi := &file_deploy_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1405,7 +1506,7 @@ func (x *ReleaseInfo) String() string { func (*ReleaseInfo) ProtoMessage() {} func (x *ReleaseInfo) ProtoReflect() protoreflect.Message { - mi := &file_deploy_proto_msgTypes[14] + mi := &file_deploy_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1418,7 +1519,7 @@ func (x *ReleaseInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ReleaseInfo.ProtoReflect.Descriptor instead. func (*ReleaseInfo) Descriptor() ([]byte, []int) { - return file_deploy_proto_rawDescGZIP(), []int{14} + return file_deploy_proto_rawDescGZIP(), []int{16} } func (x *ReleaseInfo) GetDistro() string { @@ -1461,7 +1562,7 @@ type SaveToGlanceParams struct { func (x *SaveToGlanceParams) Reset() { *x = SaveToGlanceParams{} if protoimpl.UnsafeEnabled { - mi := &file_deploy_proto_msgTypes[15] + mi := &file_deploy_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1474,7 +1575,7 @@ func (x *SaveToGlanceParams) String() string { func (*SaveToGlanceParams) ProtoMessage() {} func (x *SaveToGlanceParams) ProtoReflect() protoreflect.Message { - mi := &file_deploy_proto_msgTypes[15] + mi := &file_deploy_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1487,7 +1588,7 @@ func (x *SaveToGlanceParams) ProtoReflect() protoreflect.Message { // Deprecated: Use SaveToGlanceParams.ProtoReflect.Descriptor instead. func (*SaveToGlanceParams) Descriptor() ([]byte, []int) { - return file_deploy_proto_rawDescGZIP(), []int{15} + return file_deploy_proto_rawDescGZIP(), []int{17} } func (x *SaveToGlanceParams) GetDiskInfo() *DiskInfo { @@ -1516,7 +1617,7 @@ type SaveToGlanceResponse struct { func (x *SaveToGlanceResponse) Reset() { *x = SaveToGlanceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_deploy_proto_msgTypes[16] + mi := &file_deploy_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1529,7 +1630,7 @@ func (x *SaveToGlanceResponse) String() string { func (*SaveToGlanceResponse) ProtoMessage() {} func (x *SaveToGlanceResponse) ProtoReflect() protoreflect.Message { - mi := &file_deploy_proto_msgTypes[16] + mi := &file_deploy_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1542,7 +1643,7 @@ func (x *SaveToGlanceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SaveToGlanceResponse.ProtoReflect.Descriptor instead. func (*SaveToGlanceResponse) Descriptor() ([]byte, []int) { - return file_deploy_proto_rawDescGZIP(), []int{16} + return file_deploy_proto_rawDescGZIP(), []int{18} } func (x *SaveToGlanceResponse) GetOsInfo() string { @@ -1570,7 +1671,7 @@ type ProbeImageInfoPramas struct { func (x *ProbeImageInfoPramas) Reset() { *x = ProbeImageInfoPramas{} if protoimpl.UnsafeEnabled { - mi := &file_deploy_proto_msgTypes[17] + mi := &file_deploy_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1583,7 +1684,7 @@ func (x *ProbeImageInfoPramas) String() string { func (*ProbeImageInfoPramas) ProtoMessage() {} func (x *ProbeImageInfoPramas) ProtoReflect() protoreflect.Message { - mi := &file_deploy_proto_msgTypes[17] + mi := &file_deploy_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1596,7 +1697,7 @@ func (x *ProbeImageInfoPramas) ProtoReflect() protoreflect.Message { // Deprecated: Use ProbeImageInfoPramas.ProtoReflect.Descriptor instead. func (*ProbeImageInfoPramas) Descriptor() ([]byte, []int) { - return file_deploy_proto_rawDescGZIP(), []int{17} + return file_deploy_proto_rawDescGZIP(), []int{19} } func (x *ProbeImageInfoPramas) GetDiskInfo() *DiskInfo { @@ -1623,7 +1724,7 @@ type ImageInfo struct { func (x *ImageInfo) Reset() { *x = ImageInfo{} if protoimpl.UnsafeEnabled { - mi := &file_deploy_proto_msgTypes[18] + mi := &file_deploy_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1636,7 +1737,7 @@ func (x *ImageInfo) String() string { func (*ImageInfo) ProtoMessage() {} func (x *ImageInfo) ProtoReflect() protoreflect.Message { - mi := &file_deploy_proto_msgTypes[18] + mi := &file_deploy_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1649,7 +1750,7 @@ func (x *ImageInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ImageInfo.ProtoReflect.Descriptor instead. func (*ImageInfo) Descriptor() ([]byte, []int) { - return file_deploy_proto_rawDescGZIP(), []int{18} + return file_deploy_proto_rawDescGZIP(), []int{20} } func (x *ImageInfo) GetOsInfo() *ReleaseInfo { @@ -1712,7 +1813,7 @@ type EsxiDiskInfo struct { func (x *EsxiDiskInfo) Reset() { *x = EsxiDiskInfo{} if protoimpl.UnsafeEnabled { - mi := &file_deploy_proto_msgTypes[19] + mi := &file_deploy_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1725,7 +1826,7 @@ func (x *EsxiDiskInfo) String() string { func (*EsxiDiskInfo) ProtoMessage() {} func (x *EsxiDiskInfo) ProtoReflect() protoreflect.Message { - mi := &file_deploy_proto_msgTypes[19] + mi := &file_deploy_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1738,7 +1839,7 @@ func (x *EsxiDiskInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use EsxiDiskInfo.ProtoReflect.Descriptor instead. func (*EsxiDiskInfo) Descriptor() ([]byte, []int) { - return file_deploy_proto_rawDescGZIP(), []int{19} + return file_deploy_proto_rawDescGZIP(), []int{21} } func (x *EsxiDiskInfo) GetDiskPath() string { @@ -1760,7 +1861,7 @@ type ConnectEsxiDisksParams struct { func (x *ConnectEsxiDisksParams) Reset() { *x = ConnectEsxiDisksParams{} if protoimpl.UnsafeEnabled { - mi := &file_deploy_proto_msgTypes[20] + mi := &file_deploy_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1773,7 +1874,7 @@ func (x *ConnectEsxiDisksParams) String() string { func (*ConnectEsxiDisksParams) ProtoMessage() {} func (x *ConnectEsxiDisksParams) ProtoReflect() protoreflect.Message { - mi := &file_deploy_proto_msgTypes[20] + mi := &file_deploy_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1786,7 +1887,7 @@ func (x *ConnectEsxiDisksParams) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectEsxiDisksParams.ProtoReflect.Descriptor instead. func (*ConnectEsxiDisksParams) Descriptor() ([]byte, []int) { - return file_deploy_proto_rawDescGZIP(), []int{20} + return file_deploy_proto_rawDescGZIP(), []int{22} } func (x *ConnectEsxiDisksParams) GetVddkInfo() *VDDKConInfo { @@ -1814,7 +1915,7 @@ type EsxiDisksConnectionInfo struct { func (x *EsxiDisksConnectionInfo) Reset() { *x = EsxiDisksConnectionInfo{} if protoimpl.UnsafeEnabled { - mi := &file_deploy_proto_msgTypes[21] + mi := &file_deploy_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1827,7 +1928,7 @@ func (x *EsxiDisksConnectionInfo) String() string { func (*EsxiDisksConnectionInfo) ProtoMessage() {} func (x *EsxiDisksConnectionInfo) ProtoReflect() protoreflect.Message { - mi := &file_deploy_proto_msgTypes[21] + mi := &file_deploy_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1840,7 +1941,7 @@ func (x *EsxiDisksConnectionInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use EsxiDisksConnectionInfo.ProtoReflect.Descriptor instead. func (*EsxiDisksConnectionInfo) Descriptor() ([]byte, []int) { - return file_deploy_proto_rawDescGZIP(), []int{21} + return file_deploy_proto_rawDescGZIP(), []int{23} } func (x *EsxiDisksConnectionInfo) GetDisks() []*EsxiDiskInfo { @@ -2046,104 +2147,115 @@ var file_deploy_proto_rawDesc = []byte{ 0x76, 0x69, 0x73, 0x6f, 0x72, 0x12, 0x2e, 0x0a, 0x09, 0x76, 0x64, 0x64, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x56, 0x44, 0x44, 0x4b, 0x43, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x76, 0x64, 0x64, - 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x6e, 0x0a, 0x0e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x46, - 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, - 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, - 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x73, 0x46, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0x6f, 0x0a, 0x0b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x73, 0x74, 0x72, 0x6f, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73, 0x74, 0x72, 0x6f, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, - 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, - 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x22, 0x5d, 0x0a, 0x12, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, - 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2b, 0x0a, 0x09, + 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x3a, 0x0a, 0x0e, 0x46, 0x73, 0x45, 0x78, 0x74, 0x34, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x43, 0x61, 0x73, 0x65, 0x49, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0f, 0x43, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x22, 0x36, 0x0a, 0x0a, 0x46, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, + 0x28, 0x0a, 0x04, 0x65, 0x78, 0x74, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x61, 0x70, 0x69, 0x73, 0x2e, 0x46, 0x73, 0x45, 0x78, 0x74, 0x34, 0x46, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x52, 0x04, 0x65, 0x78, 0x74, 0x34, 0x22, 0xa1, 0x01, 0x0a, 0x0e, 0x46, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x46, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x22, 0x65, 0x0a, 0x14, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, - 0x07, 0x6f, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x6f, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x34, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, - 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x43, 0x0a, 0x14, - 0x50, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x50, 0x72, - 0x61, 0x6d, 0x61, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, + 0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x73, 0x5f, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x73, + 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x66, 0x73, + 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x46, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x52, 0x0a, 0x66, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x6f, 0x0a, + 0x0b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, + 0x64, 0x69, 0x73, 0x74, 0x72, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, + 0x73, 0x74, 0x72, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, + 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x22, 0x5d, + 0x0a, 0x12, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, - 0x6f, 0x22, 0xb2, 0x02, 0x0a, 0x09, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x2a, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x6f, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x17, 0x0a, 0x07, 0x6f, - 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x73, 0x5f, 0x75, 0x65, 0x66, 0x69, 0x5f, - 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, - 0x73, 0x55, 0x65, 0x66, 0x69, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x28, 0x0a, 0x10, - 0x69, 0x73, 0x5f, 0x6c, 0x76, 0x6d, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x4c, 0x76, 0x6d, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, - 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, - 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x68, 0x79, 0x73, 0x69, - 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, - 0x61, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x35, 0x0a, 0x17, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x5f, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x14, 0x69, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x43, 0x6c, 0x6f, - 0x75, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x22, 0x2b, 0x0a, 0x0c, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, - 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x50, - 0x61, 0x74, 0x68, 0x22, 0x7d, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x73, - 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2e, 0x0a, - 0x09, 0x76, 0x64, 0x64, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x56, 0x44, 0x44, 0x4b, 0x43, 0x6f, 0x6e, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x76, 0x64, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, - 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, - 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, - 0x66, 0x6f, 0x22, 0x43, 0x0a, 0x17, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x0a, - 0x05, 0x64, 0x69, 0x73, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, - 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x05, 0x64, 0x69, 0x73, 0x6b, 0x73, 0x32, 0xc6, 0x03, 0x0a, 0x0b, 0x44, 0x65, 0x70, 0x6c, - 0x6f, 0x79, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x47, 0x75, 0x65, 0x73, 0x74, 0x46, 0x73, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1b, 0x2e, 0x61, - 0x70, 0x69, 0x73, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x47, 0x75, 0x65, 0x73, 0x74, 0x46, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x52, 0x65, 0x73, - 0x69, 0x7a, 0x65, 0x46, 0x73, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x73, - 0x69, 0x7a, 0x65, 0x46, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, - 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x2d, 0x0a, 0x08, 0x46, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x46, 0x73, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x46, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x46, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, - 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x44, 0x0a, 0x0c, 0x53, 0x61, 0x76, 0x65, 0x54, - 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x53, - 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, - 0x0e, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, 0x61, 0x67, - 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x50, 0x72, 0x61, 0x6d, 0x61, 0x73, 0x1a, 0x0f, 0x2e, 0x61, 0x70, - 0x69, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4f, 0x0a, 0x10, + 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x22, 0x65, 0x0a, + 0x14, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x34, + 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x43, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, 0x61, + 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x50, 0x72, 0x61, 0x6d, 0x61, 0x73, 0x12, 0x2b, 0x0a, 0x09, + 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xb2, 0x02, 0x0a, 0x09, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2a, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x69, 0x6e, + 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, + 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x6f, 0x73, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, + 0x69, 0x73, 0x5f, 0x75, 0x65, 0x66, 0x69, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x55, 0x65, 0x66, 0x69, 0x53, 0x75, 0x70, + 0x70, 0x6f, 0x72, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x73, 0x5f, 0x6c, 0x76, 0x6d, 0x5f, 0x70, + 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, + 0x69, 0x73, 0x4c, 0x76, 0x6d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, + 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x12, + 0x36, 0x0a, 0x17, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x15, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x35, 0x0a, 0x17, 0x69, 0x73, 0x5f, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x69, 0x6e, + 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, 0x73, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x22, 0x2b, + 0x0a, 0x0c, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, + 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x22, 0x7d, 0x0a, 0x16, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2e, 0x0a, 0x09, 0x76, 0x64, 0x64, 0x6b, 0x5f, 0x69, 0x6e, + 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, + 0x56, 0x44, 0x44, 0x4b, 0x43, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x76, 0x64, 0x64, + 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, + 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, + 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x43, 0x0a, 0x17, 0x45, 0x73, + 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x0a, 0x05, 0x64, 0x69, 0x73, 0x6b, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, + 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x64, 0x69, 0x73, 0x6b, 0x73, 0x32, + 0xc6, 0x03, 0x0a, 0x0b, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, + 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x47, 0x75, 0x65, 0x73, 0x74, 0x46, 0x73, + 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x47, 0x75, 0x65, 0x73, 0x74, 0x46, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x46, 0x73, 0x12, 0x14, 0x2e, + 0x61, 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x46, 0x73, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x2d, 0x0a, 0x08, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x46, 0x73, 0x12, 0x14, 0x2e, 0x61, + 0x70, 0x69, 0x73, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x46, 0x73, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x44, 0x0a, 0x0c, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x73, + 0x2e, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x50, + 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x50, 0x72, 0x61, + 0x6d, 0x61, 0x73, 0x1a, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4f, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, + 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, - 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, - 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1d, - 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x41, 0x0a, - 0x13, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x73, 0x78, 0x69, 0x44, - 0x69, 0x73, 0x6b, 0x73, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, - 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x6e, 0x66, 0x6f, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x42, 0x34, 0x5a, 0x32, 0x79, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x2e, 0x69, 0x6f, 0x2f, 0x78, 0x2f, - 0x6f, 0x6e, 0x65, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x68, 0x6f, 0x73, - 0x74, 0x6d, 0x61, 0x6e, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, - 0x72, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, + 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x41, 0x0a, 0x13, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x12, 0x1d, 0x2e, 0x61, + 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x0b, 0x2e, 0x61, 0x70, + 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x34, 0x5a, 0x32, 0x79, 0x75, 0x6e, 0x69, + 0x6f, 0x6e, 0x2e, 0x69, 0x6f, 0x2f, 0x78, 0x2f, 0x6f, 0x6e, 0x65, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2f, 0x68, 0x6f, 0x73, + 0x74, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2158,7 +2270,7 @@ func file_deploy_proto_rawDescGZIP() []byte { return file_deploy_proto_rawDescData } -var file_deploy_proto_msgTypes = make([]protoimpl.MessageInfo, 22) +var file_deploy_proto_msgTypes = make([]protoimpl.MessageInfo, 24) var file_deploy_proto_goTypes = []interface{}{ (*GuestDesc)(nil), // 0: apis.GuestDesc (*Disk)(nil), // 1: apis.Disk @@ -2173,15 +2285,17 @@ var file_deploy_proto_goTypes = []interface{}{ (*DiskInfo)(nil), // 10: apis.DiskInfo (*DeployParams)(nil), // 11: apis.DeployParams (*ResizeFsParams)(nil), // 12: apis.ResizeFsParams - (*FormatFsParams)(nil), // 13: apis.FormatFsParams - (*ReleaseInfo)(nil), // 14: apis.ReleaseInfo - (*SaveToGlanceParams)(nil), // 15: apis.SaveToGlanceParams - (*SaveToGlanceResponse)(nil), // 16: apis.SaveToGlanceResponse - (*ProbeImageInfoPramas)(nil), // 17: apis.ProbeImageInfoPramas - (*ImageInfo)(nil), // 18: apis.ImageInfo - (*EsxiDiskInfo)(nil), // 19: apis.EsxiDiskInfo - (*ConnectEsxiDisksParams)(nil), // 20: apis.ConnectEsxiDisksParams - (*EsxiDisksConnectionInfo)(nil), // 21: apis.EsxiDisksConnectionInfo + (*FsExt4Features)(nil), // 13: apis.FsExt4Features + (*FsFeatures)(nil), // 14: apis.FsFeatures + (*FormatFsParams)(nil), // 15: apis.FormatFsParams + (*ReleaseInfo)(nil), // 16: apis.ReleaseInfo + (*SaveToGlanceParams)(nil), // 17: apis.SaveToGlanceParams + (*SaveToGlanceResponse)(nil), // 18: apis.SaveToGlanceResponse + (*ProbeImageInfoPramas)(nil), // 19: apis.ProbeImageInfoPramas + (*ImageInfo)(nil), // 20: apis.ImageInfo + (*EsxiDiskInfo)(nil), // 21: apis.EsxiDiskInfo + (*ConnectEsxiDisksParams)(nil), // 22: apis.ConnectEsxiDisksParams + (*EsxiDisksConnectionInfo)(nil), // 23: apis.EsxiDisksConnectionInfo } var file_deploy_proto_depIdxs = []int32{ 2, // 0: apis.GuestDesc.nics:type_name -> apis.Nic @@ -2196,33 +2310,35 @@ var file_deploy_proto_depIdxs = []int32{ 3, // 9: apis.DeployParams.vddk_info:type_name -> apis.VDDKConInfo 10, // 10: apis.ResizeFsParams.disk_info:type_name -> apis.DiskInfo 3, // 11: apis.ResizeFsParams.vddk_info:type_name -> apis.VDDKConInfo - 10, // 12: apis.FormatFsParams.disk_info:type_name -> apis.DiskInfo - 10, // 13: apis.SaveToGlanceParams.disk_info:type_name -> apis.DiskInfo - 14, // 14: apis.SaveToGlanceResponse.release_info:type_name -> apis.ReleaseInfo - 10, // 15: apis.ProbeImageInfoPramas.disk_info:type_name -> apis.DiskInfo - 14, // 16: apis.ImageInfo.os_info:type_name -> apis.ReleaseInfo - 3, // 17: apis.ConnectEsxiDisksParams.vddk_info:type_name -> apis.VDDKConInfo - 19, // 18: apis.ConnectEsxiDisksParams.access_info:type_name -> apis.EsxiDiskInfo - 19, // 19: apis.EsxiDisksConnectionInfo.disks:type_name -> apis.EsxiDiskInfo - 11, // 20: apis.DeployAgent.DeployGuestFs:input_type -> apis.DeployParams - 12, // 21: apis.DeployAgent.ResizeFs:input_type -> apis.ResizeFsParams - 13, // 22: apis.DeployAgent.FormatFs:input_type -> apis.FormatFsParams - 15, // 23: apis.DeployAgent.SaveToGlance:input_type -> apis.SaveToGlanceParams - 17, // 24: apis.DeployAgent.ProbeImageInfo:input_type -> apis.ProbeImageInfoPramas - 20, // 25: apis.DeployAgent.ConnectEsxiDisks:input_type -> apis.ConnectEsxiDisksParams - 21, // 26: apis.DeployAgent.DisconnectEsxiDisks:input_type -> apis.EsxiDisksConnectionInfo - 9, // 27: apis.DeployAgent.DeployGuestFs:output_type -> apis.DeployGuestFsResponse - 8, // 28: apis.DeployAgent.ResizeFs:output_type -> apis.Empty - 8, // 29: apis.DeployAgent.FormatFs:output_type -> apis.Empty - 16, // 30: apis.DeployAgent.SaveToGlance:output_type -> apis.SaveToGlanceResponse - 18, // 31: apis.DeployAgent.ProbeImageInfo:output_type -> apis.ImageInfo - 21, // 32: apis.DeployAgent.ConnectEsxiDisks:output_type -> apis.EsxiDisksConnectionInfo - 8, // 33: apis.DeployAgent.DisconnectEsxiDisks:output_type -> apis.Empty - 27, // [27:34] is the sub-list for method output_type - 20, // [20:27] is the sub-list for method input_type - 20, // [20:20] is the sub-list for extension type_name - 20, // [20:20] is the sub-list for extension extendee - 0, // [0:20] is the sub-list for field type_name + 13, // 12: apis.FsFeatures.ext4:type_name -> apis.FsExt4Features + 10, // 13: apis.FormatFsParams.disk_info:type_name -> apis.DiskInfo + 14, // 14: apis.FormatFsParams.fs_features:type_name -> apis.FsFeatures + 10, // 15: apis.SaveToGlanceParams.disk_info:type_name -> apis.DiskInfo + 16, // 16: apis.SaveToGlanceResponse.release_info:type_name -> apis.ReleaseInfo + 10, // 17: apis.ProbeImageInfoPramas.disk_info:type_name -> apis.DiskInfo + 16, // 18: apis.ImageInfo.os_info:type_name -> apis.ReleaseInfo + 3, // 19: apis.ConnectEsxiDisksParams.vddk_info:type_name -> apis.VDDKConInfo + 21, // 20: apis.ConnectEsxiDisksParams.access_info:type_name -> apis.EsxiDiskInfo + 21, // 21: apis.EsxiDisksConnectionInfo.disks:type_name -> apis.EsxiDiskInfo + 11, // 22: apis.DeployAgent.DeployGuestFs:input_type -> apis.DeployParams + 12, // 23: apis.DeployAgent.ResizeFs:input_type -> apis.ResizeFsParams + 15, // 24: apis.DeployAgent.FormatFs:input_type -> apis.FormatFsParams + 17, // 25: apis.DeployAgent.SaveToGlance:input_type -> apis.SaveToGlanceParams + 19, // 26: apis.DeployAgent.ProbeImageInfo:input_type -> apis.ProbeImageInfoPramas + 22, // 27: apis.DeployAgent.ConnectEsxiDisks:input_type -> apis.ConnectEsxiDisksParams + 23, // 28: apis.DeployAgent.DisconnectEsxiDisks:input_type -> apis.EsxiDisksConnectionInfo + 9, // 29: apis.DeployAgent.DeployGuestFs:output_type -> apis.DeployGuestFsResponse + 8, // 30: apis.DeployAgent.ResizeFs:output_type -> apis.Empty + 8, // 31: apis.DeployAgent.FormatFs:output_type -> apis.Empty + 18, // 32: apis.DeployAgent.SaveToGlance:output_type -> apis.SaveToGlanceResponse + 20, // 33: apis.DeployAgent.ProbeImageInfo:output_type -> apis.ImageInfo + 23, // 34: apis.DeployAgent.ConnectEsxiDisks:output_type -> apis.EsxiDisksConnectionInfo + 8, // 35: apis.DeployAgent.DisconnectEsxiDisks:output_type -> apis.Empty + 29, // [29:36] is the sub-list for method output_type + 22, // [22:29] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name } func init() { file_deploy_proto_init() } @@ -2388,7 +2504,7 @@ func file_deploy_proto_init() { } } file_deploy_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FormatFsParams); i { + switch v := v.(*FsExt4Features); i { case 0: return &v.state case 1: @@ -2400,7 +2516,7 @@ func file_deploy_proto_init() { } } file_deploy_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReleaseInfo); i { + switch v := v.(*FsFeatures); i { case 0: return &v.state case 1: @@ -2412,7 +2528,7 @@ func file_deploy_proto_init() { } } file_deploy_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SaveToGlanceParams); i { + switch v := v.(*FormatFsParams); i { case 0: return &v.state case 1: @@ -2424,7 +2540,7 @@ func file_deploy_proto_init() { } } file_deploy_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SaveToGlanceResponse); i { + switch v := v.(*ReleaseInfo); i { case 0: return &v.state case 1: @@ -2436,7 +2552,7 @@ func file_deploy_proto_init() { } } file_deploy_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProbeImageInfoPramas); i { + switch v := v.(*SaveToGlanceParams); i { case 0: return &v.state case 1: @@ -2448,7 +2564,7 @@ func file_deploy_proto_init() { } } file_deploy_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ImageInfo); i { + switch v := v.(*SaveToGlanceResponse); i { case 0: return &v.state case 1: @@ -2460,7 +2576,7 @@ func file_deploy_proto_init() { } } file_deploy_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EsxiDiskInfo); i { + switch v := v.(*ProbeImageInfoPramas); i { case 0: return &v.state case 1: @@ -2472,7 +2588,7 @@ func file_deploy_proto_init() { } } file_deploy_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConnectEsxiDisksParams); i { + switch v := v.(*ImageInfo); i { case 0: return &v.state case 1: @@ -2484,6 +2600,30 @@ func file_deploy_proto_init() { } } file_deploy_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EsxiDiskInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_deploy_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ConnectEsxiDisksParams); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_deploy_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EsxiDisksConnectionInfo); i { case 0: return &v.state @@ -2502,7 +2642,7 @@ func file_deploy_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_deploy_proto_rawDesc, NumEnums: 0, - NumMessages: 22, + NumMessages: 24, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/hostman/hostdeployer/apis/deploy.proto b/pkg/hostman/hostdeployer/apis/deploy.proto index f5f22a9637..8795b7576b 100644 --- a/pkg/hostman/hostdeployer/apis/deploy.proto +++ b/pkg/hostman/hostdeployer/apis/deploy.proto @@ -146,10 +146,19 @@ message ResizeFsParams { VDDKConInfo vddk_info = 3; } +message FsExt4Features { + bool CaseInsensitive = 1; +} + +message FsFeatures { + FsExt4Features ext4 = 1; +} + message FormatFsParams { DiskInfo disk_info = 1; string fs_format = 2; string uuid = 3; + FsFeatures fs_features = 4; } message ReleaseInfo { diff --git a/pkg/hostman/hostdeployer/apis/deploy_grpc.pb.go b/pkg/hostman/hostdeployer/apis/deploy_grpc.pb.go index 6d0845193b..f4bc46296b 100644 --- a/pkg/hostman/hostdeployer/apis/deploy_grpc.pb.go +++ b/pkg/hostman/hostdeployer/apis/deploy_grpc.pb.go @@ -8,7 +8,6 @@ package apis import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/hostman/storageman/disk_base.go b/pkg/hostman/storageman/disk_base.go index 38372805c3..184f0e2f4a 100644 --- a/pkg/hostman/storageman/disk_base.go +++ b/pkg/hostman/storageman/disk_base.go @@ -68,8 +68,7 @@ type IDisk interface { CreateFromSnapshotLocation(ctx context.Context, location string, size int64, encryptInfo *apis.SEncryptInfo) (jsonutils.JSONObject, error) CreateFromRbdSnapshot(ctx context.Context, snapshotId, srcDiskId, srcPool string) error CreateFromImageFuse(ctx context.Context, url string, size int64, encryptInfo *apis.SEncryptInfo) error - CreateRaw(ctx context.Context, sizeMb int, diskFormat string, fsFormat string, - encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) + CreateRaw(ctx context.Context, sizeMb int, diskFormat string, fsFormat string, fsFeatures *api.DiskFsFeatures, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) PostCreateFromImageFuse() CreateSnapshot(snapshotId string, encryptKey string, encFormat qemuimg.TEncryptFormat, encAlg seclib2.TSymEncAlg) error DeleteSnapshot(snapshotId, convertSnapshot string, blockStream bool, encryptInfo apis.SEncryptInfo) error @@ -219,14 +218,28 @@ func (d *SBaseDisk) GetSnapshotPath(snapshotId string) string { return "" } -func (d *SBaseDisk) FormatFs(fsFormat, uuid string, diskInfo *deployapi.DiskInfo) { - log.Infof("Make disk %s fs %s", uuid, fsFormat) +func ConvertDiskFsFeaturesToDeploy(fsFeatures *api.DiskFsFeatures) *deployapi.FsFeatures { + if fsFeatures == nil { + return nil + } + ret := &deployapi.FsFeatures{} + if fsFeatures.Ext4 != nil { + ret.Ext4 = &deployapi.FsExt4Features{ + CaseInsensitive: fsFeatures.Ext4.CaseInsensitive, + } + } + return ret +} + +func (d *SBaseDisk) FormatFs(fsFormat string, fsFeatures *api.DiskFsFeatures, uuid string, diskInfo *deployapi.DiskInfo) { + log.Infof("Make disk %s fs %s, features: %s", uuid, fsFormat, jsonutils.Marshal(fsFeatures)) _, err := deployclient.GetDeployClient().FormatFs( context.Background(), &deployapi.FormatFsParams{ - DiskInfo: diskInfo, - FsFormat: fsFormat, - Uuid: uuid, + DiskInfo: diskInfo, + FsFormat: fsFormat, + FsFeatures: ConvertDiskFsFeaturesToDeploy(fsFeatures), + Uuid: uuid, }, ) if err != nil { diff --git a/pkg/hostman/storageman/disk_local.go b/pkg/hostman/storageman/disk_local.go index 5372a73916..fb8b414279 100644 --- a/pkg/hostman/storageman/disk_local.go +++ b/pkg/hostman/storageman/disk_local.go @@ -342,8 +342,7 @@ func (d *SLocalDisk) CreateFromUrl(ctx context.Context, url string, size int64, return nil } -func (d *SLocalDisk) CreateRaw(ctx context.Context, sizeMB int, diskFormat, fsFormat string, - encryptInfo *apis.SEncryptInfo, uuid string, back string) (jsonutils.JSONObject, error) { +func (d *SLocalDisk) CreateRaw(ctx context.Context, sizeMB int, diskFormat string, fsFormat string, fsFeatures *api.DiskFsFeatures, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) { if fileutils2.Exists(d.GetPath()) { if err := os.Remove(d.GetPath()); err != nil { return nil, errors.Wrapf(err, "os.Remove(%s)", d.GetPath()) @@ -388,7 +387,7 @@ func (d *SLocalDisk) CreateRaw(ctx context.Context, sizeMB int, diskFormat, fsFo diskInfo.EncryptAlg = string(encryptInfo.Alg) } if utils.IsInStringArray(fsFormat, []string{"swap", "ext2", "ext3", "ext4", "xfs"}) { - d.FormatFs(fsFormat, uuid, diskInfo) + d.FormatFs(fsFormat, fsFeatures, diskId, diskInfo) } return d.GetDiskDesc(), nil diff --git a/pkg/hostman/storageman/disk_lvm.go b/pkg/hostman/storageman/disk_lvm.go index 8c59fe71fa..7f06629ab8 100644 --- a/pkg/hostman/storageman/disk_lvm.go +++ b/pkg/hostman/storageman/disk_lvm.go @@ -105,10 +105,7 @@ func (d *SLVMDisk) GetDiskDesc() jsonutils.JSONObject { return desc } -func (d *SLVMDisk) CreateRaw( - ctx context.Context, sizeMB int, diskFormat string, fsFormat string, - encryptInfo *apis.SEncryptInfo, diskId string, back string, -) (jsonutils.JSONObject, error) { +func (d *SLVMDisk) CreateRaw(ctx context.Context, sizeMB int, diskFormat string, fsFormat string, fsFeatures *api.DiskFsFeatures, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) { if fileutils2.Exists(d.GetPath()) { if err := lvmutils.LvRemove(d.GetLvPath()); err != nil { return nil, errors.Wrap(err, "CreateRaw lvremove") @@ -145,7 +142,7 @@ func (d *SLVMDisk) CreateRaw( diskInfo.EncryptAlg = string(encryptInfo.Alg) } if utils.IsInStringArray(fsFormat, []string{"swap", "ext2", "ext3", "ext4", "xfs"}) { - d.FormatFs(fsFormat, diskId, diskInfo) + d.FormatFs(fsFormat, nil, diskId, diskInfo) } return d.GetDiskDesc(), nil } diff --git a/pkg/hostman/storageman/disk_nvme.go b/pkg/hostman/storageman/disk_nvme.go index be62a77112..5bc3f26254 100644 --- a/pkg/hostman/storageman/disk_nvme.go +++ b/pkg/hostman/storageman/disk_nvme.go @@ -22,6 +22,7 @@ import ( "yunion.io/x/pkg/util/qemuimgfmt" "yunion.io/x/onecloud/pkg/apis" + api "yunion.io/x/onecloud/pkg/apis/compute" ) var _ IDisk = (*SNVMEDisk)(nil) @@ -44,10 +45,7 @@ func (d *SNVMEDisk) GetDiskDesc() jsonutils.JSONObject { return desc } -func (d *SNVMEDisk) CreateRaw( - ctx context.Context, sizeMb int, diskFormat string, fsFormat string, - encryptInfo *apis.SEncryptInfo, diskId string, back string, -) (jsonutils.JSONObject, error) { +func (d *SNVMEDisk) CreateRaw(ctx context.Context, sizeMb int, diskFormat string, fsFormat string, fsFeatures *api.DiskFsFeatures, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) { // do nothing return nil, nil } diff --git a/pkg/hostman/storageman/disk_rbd.go b/pkg/hostman/storageman/disk_rbd.go index 1a324b2870..cb692f8e14 100644 --- a/pkg/hostman/storageman/disk_rbd.go +++ b/pkg/hostman/storageman/disk_rbd.go @@ -214,7 +214,7 @@ func (d *SRBDDisk) CreateFromImageFuse(ctx context.Context, url string, size int return fmt.Errorf("Not support") } -func (d *SRBDDisk) CreateRaw(ctx context.Context, sizeMb int, diskFromat string, fsFormat string, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) { +func (d *SRBDDisk) CreateRaw(ctx context.Context, sizeMb int, diskFormat string, fsFormat string, fsFeatures *api.DiskFsFeatures, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) { if encryptInfo != nil { return nil, errors.Wrap(httperrors.ErrNotSupported, "rbd not support encryptInfo") } @@ -228,7 +228,7 @@ func (d *SRBDDisk) CreateRaw(ctx context.Context, sizeMb int, diskFromat string, Path: d.GetPath(), } if utils.IsInStringArray(fsFormat, []string{"swap", "ext2", "ext3", "ext4", "xfs"}) { - d.FormatFs(fsFormat, diskId, diskInfo) + d.FormatFs(fsFormat, nil, diskId, diskInfo) } return d.GetDiskDesc(), nil diff --git a/pkg/hostman/storageman/disk_slvm.go b/pkg/hostman/storageman/disk_slvm.go index e3a4e7840a..e6d108e396 100644 --- a/pkg/hostman/storageman/disk_slvm.go +++ b/pkg/hostman/storageman/disk_slvm.go @@ -87,11 +87,8 @@ func (d *SSLVMDisk) Probe() error { return nil } -func (d *SSLVMDisk) CreateRaw( - ctx context.Context, sizeMb int, diskFormat string, fsFormat string, - encryptInfo *apis.SEncryptInfo, diskId string, back string, -) (jsonutils.JSONObject, error) { - ret, err := d.SLVMDisk.CreateRaw(ctx, sizeMb, diskFormat, fsFormat, encryptInfo, diskId, back) +func (d *SSLVMDisk) CreateRaw(ctx context.Context, sizeMb int, diskFormat string, fsFormat string, fsFeatures *api.DiskFsFeatures, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) { + ret, err := d.SLVMDisk.CreateRaw(ctx, sizeMb, diskFormat, fsFormat, nil, encryptInfo, diskId, back) if err != nil { return ret, err } @@ -284,7 +281,7 @@ func (d *SSLVMDisk) PrepareSaveToGlance(ctx context.Context, params interface{}) } func (d *SSLVMDisk) CreateFromSnapshotLocation(ctx context.Context, snapshotLocation string, size int64, encryptInfo *apis.SEncryptInfo) (jsonutils.JSONObject, error) { - ret, err := d.SLVMDisk.CreateRaw(ctx, int(size), "", "", encryptInfo, d.Id, snapshotLocation) + ret, err := d.SLVMDisk.CreateRaw(ctx, int(size), "", "", nil, encryptInfo, d.Id, snapshotLocation) if err != nil { return nil, err } diff --git a/pkg/hostman/storageman/storage_base.go b/pkg/hostman/storageman/storage_base.go index 146cc5120a..e92a454139 100644 --- a/pkg/hostman/storageman/storage_base.go +++ b/pkg/hostman/storageman/storage_base.go @@ -415,7 +415,11 @@ func (s *SBaseStorage) CreateRawDisk(ctx context.Context, disk IDisk, input *SDi if input.DiskInfo.Encryption { encryptInfo = &input.DiskInfo.EncryptInfo } - return disk.CreateRaw(ctx, input.DiskInfo.DiskSizeMb, input.DiskInfo.Format, input.DiskInfo.FsFormat, encryptInfo, input.DiskId, "") + return disk.CreateRaw(ctx, input.DiskInfo.DiskSizeMb, + input.DiskInfo.Format, + input.DiskInfo.FsFormat, + input.DiskInfo.FsFeatures, + encryptInfo, input.DiskId, "") } func (s *SBaseStorage) CreateDiskFromTemplate(ctx context.Context, disk IDisk, input *SDiskCreateByDiskinfo) (jsonutils.JSONObject, error) { diff --git a/pkg/hostman/storageman/storage_local.go b/pkg/hostman/storageman/storage_local.go index 09dcacc7b2..c33196ae13 100644 --- a/pkg/hostman/storageman/storage_local.go +++ b/pkg/hostman/storageman/storage_local.go @@ -815,7 +815,7 @@ func (s *SLocalStorage) DestinationPrepareMigrate( if liveMigrate { // create local disk backingFile, _ := disksBackingFile.GetString(diskId) - _, err := disk.CreateRaw(ctx, int(diskinfo.Size), "qcow2", "", encInfo, "", backingFile) + _, err := disk.CreateRaw(ctx, int(diskinfo.Size), "qcow2", "", nil, encInfo, "", backingFile) if err != nil { log.Errorln(err) return err diff --git a/pkg/hostman/storageman/storage_lvm.go b/pkg/hostman/storageman/storage_lvm.go index 27528c9ac5..19efd2d929 100644 --- a/pkg/hostman/storageman/storage_lvm.go +++ b/pkg/hostman/storageman/storage_lvm.go @@ -453,7 +453,7 @@ func (s *SLVMStorage) DestinationPrepareMigrate( if liveMigrate { // create local disk backingFile, _ := disksBackingFile.GetString(diskId) - _, err := disk.CreateRaw(ctx, int(diskinfo.Size), "qcow2", "", encInfo, "", backingFile) + _, err := disk.CreateRaw(ctx, int(diskinfo.Size), "qcow2", "", nil, encInfo, "", backingFile) if err != nil { log.Errorln(err) return err diff --git a/pkg/mcclient/options/compute/containers.go b/pkg/mcclient/options/compute/containers.go index 9609bbde71..73d1c06c15 100644 --- a/pkg/mcclient/options/compute/containers.go +++ b/pkg/mcclient/options/compute/containers.go @@ -52,7 +52,7 @@ type ContainerCreateCommonOptions struct { Args []string `help:"Args for the Command (i.e. command for docker)" json:"args"` WorkingDir string `help:"Current working directory of the command" json:"working_dir"` Env []string `help:"List of environment variable to set in the container and the format is: ="` - VolumeMount []string `help:"Volume mount of the container and the format is: name=,mount=,readonly=,disk_index=,disk_id="` + VolumeMount []string `help:"Volume mount of the container and the format is: name=,mount=,readonly=,case_insensitive=,disk_index=,disk_id="` Device []string `help:"Host device: ::, e.g.: /dev/snd:/dev/snd:rwm"` Privileged bool `help:"Privileged mode"` Caps string `help:"Container capabilities, e.g.: SETPCAP,AUDIT_WRITE,SYS_CHROOT,CHOWN,DAC_OVERRIDE,FOWNER,SETGID,SETUID,SYSLOG,SYS_ADMIN,WAKE_ALARM,SYS_PTRACE,BLOCK_SUSPEND,MKNOD,KILL,SYS_RESOURCE,NET_RAW,NET_ADMIN,NET_BIND_SERVICE,SYS_NICE"` @@ -237,6 +237,10 @@ func parseContainerVolumeMount(vmStr string) (*apis.ContainerVolumeMount, error) vm.Disk = &apis.ContainerVolumeMountDisk{} } vm.Disk.StorageSizeFile = val + case "case_insensitive", "casefold": + if strings.ToLower(val) == "true" { + vm.Disk.CaseInsensitive = true + } case "overlay": if vm.Disk == nil { vm.Disk = &apis.ContainerVolumeMountDisk{} diff --git a/pkg/mcclient/options/compute/servers.go b/pkg/mcclient/options/compute/servers.go index e862490de5..254ed29121 100644 --- a/pkg/mcclient/options/compute/servers.go +++ b/pkg/mcclient/options/compute/servers.go @@ -261,6 +261,7 @@ type ServerCreateCommonConfig struct { Disk descriptions size: 500M, 10G fs: swap, ext2, ext3, ext4, xfs, ntfs, fat, hfsplus + fs_features: casefold format: qcow2, raw, docker, iso, vmdk, vmdkflatver1, vmdkflatver2, vmdkflat, vmdksparse, vmdksparsever1, vmdksparsever2, vmdksesparse, vhd driver: virtio, ide, scsi, sata, pvscsi cache_mod: writeback, none, writethrough