diff --git a/cmd/controller/disk.go b/cmd/controller/disk.go index 5e73e8e05..2271e8a8c 100644 --- a/cmd/controller/disk.go +++ b/cmd/controller/disk.go @@ -18,6 +18,7 @@ package controller import ( apis "github.com/openebs/node-disk-manager/pkg/apis/openebs.io/v1alpha1" + udev "github.com/openebs/node-disk-manager/pkg/udev" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -45,6 +46,8 @@ type DiskInfo struct { Compliance string // Compliance is implemented specifications version i.e. SPC-1, SPC-2, etc DiskType string // DiskType represents the type of disk like Disk, Sparse etc., DriveType string // DriveType represents the type of disk like HHD, HDD etc., + FileSystemInfo string // FileSystemInfo stores the filesystem on the disk. Can be none, xfs, ext4 etc + PartitionData []PartitionInfo // Information of the partitions on the disk //Stats of disk which keep changing TotalBytesRead uint64 @@ -78,6 +81,11 @@ type ProbeIdentifier struct { SeachestIdentifier string // SeachestIdentifier (devPath) is used to identify disk by seachest. } +type PartitionInfo struct { + PartitionType string // Partition type like 83, 8e etc. + FileSystem string // Filesystem of partition. can be none, xfs etc. +} + // NewDiskInfo returns a pointer of empty diskInfo struct which will // be field by different probes each probe will responsible for // populate some specific fields of DiskInfo struct. @@ -98,6 +106,17 @@ func (di *DiskInfo) ToDisk() apis.Disk { return dr } +// ToPartition convert the PartitionData struct inside DiskInfo to apis.Partition +// which will be used to include the parition information in the Disk CR +func (di *DiskInfo) ToPartition() []apis.Partition { + partition := make([]apis.Partition, 0) + for _, partitionData := range di.PartitionData { + partition = append(partition, apis.Partition{PartitionType: partitionData.PartitionType, + FileSystemType: partitionData.FileSystem}) + } + return partition +} + // getObjectMeta returns ObjectMeta struct which contains labels and Name of resource // It is used to populate data of Disk struct which is a disk CR. func (di *DiskInfo) getObjectMeta() metav1.ObjectMeta { @@ -140,6 +159,9 @@ func (di *DiskInfo) getDiskSpec() apis.DiskSpec { diskSpec.Path = di.getPath() diskSpec.Details = di.getDiskDetails() diskSpec.Capacity = di.getDiskCapacity() + if di.FileSystemInfo != udev.UDEV_FS_NONE { + diskSpec.FileSystem = di.FileSystemInfo + } diskSpec.DevLinks = di.getDiskLinks() return diskSpec } diff --git a/cmd/probe/eventhandler.go b/cmd/probe/eventhandler.go index 7953cde6c..745c382c2 100644 --- a/cmd/probe/eventhandler.go +++ b/cmd/probe/eventhandler.go @@ -54,7 +54,29 @@ func (pe *ProbeEvent) addDiskEvent(msg controller.EventMessage) { } glog.Info("processed data for ", diskDetails.ProbeIdentifiers.Uuid) oldDr := pe.Controller.GetExistingResource(diskList, diskDetails.ProbeIdentifiers.Uuid) - pe.Controller.PushDiskResource(oldDr, diskDetails) + // if old DiskCR doesn't exist and parition is found, it is ignored since we don't need info + // of partition if disk as a whole is ignored + if oldDr == nil && len(diskDetails.PartitionData) != 0 { + glog.Info("Skipping partition of already excluded disk ", diskDetails.ProbeIdentifiers.Uuid) + continue + } + // if diskCR is already present, and udev event is generated for partition, append the partition info + // to the diskCR + if oldDr != nil && len(diskDetails.PartitionData) != 0 { + newDrCopy := oldDr.DeepCopy() + glog.Info("Appending partition data to ", diskDetails.ProbeIdentifiers.Uuid) + newDrCopy.Spec.PartitionDetails = append(newDrCopy.Spec.PartitionDetails, diskDetails.ToPartition()...) + pe.Controller.UpdateDisk(*newDrCopy, oldDr) + } else { + pe.Controller.PushDiskResource(oldDr, diskDetails) + } + /// update the list of DiskCRs + diskList, err = pe.Controller.ListDiskResource() + if err != nil { + glog.Error(err) + go pe.initOrErrorEvent() + return + } } } @@ -87,6 +109,7 @@ func (pe *ProbeEvent) deleteDiskEvent(msg controller.EventMessage) { // used for initial setup and when any uid mismatch or error occurred. func (pe *ProbeEvent) initOrErrorEvent() { udevProbe := newUdevProbe(pe.Controller) + defer udevProbe.free() err := udevProbe.scan() if err != nil { glog.Error(err) diff --git a/cmd/probe/udevprobe.go b/cmd/probe/udevprobe.go index d4977a7e9..638f8d521 100644 --- a/cmd/probe/udevprobe.go +++ b/cmd/probe/udevprobe.go @@ -139,12 +139,20 @@ func (up *udevProbe) scan() error { if err != nil { continue } - if newUdevice.IsDisk() { + if newUdevice.IsDisk() || newUdevice.IsParitition() { uuid := newUdevice.GetUid() disksUid = append(disksUid, uuid) deviceDetails := &controller.DiskInfo{} deviceDetails.ProbeIdentifiers.Uuid = uuid deviceDetails.ProbeIdentifiers.UdevIdentifier = newUdevice.GetSyspath() + if newUdevice.IsParitition() { + partitionData := controller.PartitionInfo{ + PartitionType: newUdevice.GetPartitionType(), + FileSystem: newUdevice.GetFileSystemInfo(), + } + deviceDetails.PartitionData = append(deviceDetails.PartitionData, partitionData) + glog.Info("Partition Data for ", uuid, " : ", deviceDetails.PartitionData) + } diskInfo = append(diskInfo, deviceDetails) } newUdevice.UdevDeviceUnref() @@ -154,6 +162,7 @@ func (up *udevProbe) scan() error { Action: libudevwrapper.UDEV_ACTION_ADD, Devices: diskInfo, } + glog.Info("Partition Data to channel: ", eventDetails.Devices[3].PartitionData) udevevent.UdevEventMessageChannel <- eventDetails return nil } @@ -171,6 +180,7 @@ func (up *udevProbe) FillDiskDetails(d *controller.DiskInfo) { d.Vendor = udevDiskDetails.Vendor d.ByIdDevLinks = udevDiskDetails.ByIdDevLinks d.ByPathDevLinks = udevDiskDetails.ByPathDevLinks + d.FileSystemInfo = udevDiskDetails.FileSystem } // listen listens for event message over UdevEventMessages channel diff --git a/cmd/probe/udevprobe_test.go b/cmd/probe/udevprobe_test.go index 7890e6337..230cae8d1 100644 --- a/cmd/probe/udevprobe_test.go +++ b/cmd/probe/udevprobe_test.go @@ -113,6 +113,7 @@ func TestFillDiskDetails(t *testing.T) { expectedDiskInfo.DiskType = "disk" expectedDiskInfo.ByIdDevLinks = mockOsDiskDetails.ByIdDevLinks expectedDiskInfo.ByPathDevLinks = mockOsDiskDetails.ByPathDevLinks + expectedDiskInfo.FileSystemInfo = mockOsDiskDetails.FileSystem assert.Equal(t, expectedDiskInfo, actualDiskInfo) } diff --git a/pkg/apis/openebs.io/v1alpha1/types.go b/pkg/apis/openebs.io/v1alpha1/types.go index 2a81b5e03..e3a79fda8 100644 --- a/pkg/apis/openebs.io/v1alpha1/types.go +++ b/pkg/apis/openebs.io/v1alpha1/types.go @@ -22,10 +22,12 @@ type Disk struct { // DiskSpec is the specification for the disk stored as CRD type DiskSpec struct { - Path string `json:"path"` //Path contain devpath (e.g. /dev/sdb) - Capacity DiskCapacity `json:"capacity"` //Capacity - Details DiskDetails `json:"details"` //Details contains static attributes (model, serial ..) - DevLinks []DiskDevLink `json:"devlinks,omitempty"` //DevLinks contains soft links of one disk + Path string `json:"path"` //Path contain devpath (e.g. /dev/sdb) + Capacity DiskCapacity `json:"capacity"` //Capacity + Details DiskDetails `json:"details"` //Details contains static attributes (model, serial ..) + FileSystem string `json:"fileSystem,omitempty"` //Contains the data about filesystem on the disk + PartitionDetails []Partition `json:"partitionDetails,omitempty"` //Details of partitions in the disk (filesystem, partition type) + DevLinks []DiskDevLink `json:"devlinks,omitempty"` //DevLinks contains soft links of one disk } type DiskStatus struct { @@ -33,15 +35,15 @@ type DiskStatus struct { } type DiskCapacity struct { - Storage uint64 `json:"storage"` // disk size in bytes - PhysicalSectorSize uint32 `json: "physicalSectorSize"` // disk physical-Sector size in bytes - LogicalSectorSize uint32 `json:"logicalSectorSize"` // disk logical-sector size in bytes + Storage uint64 `json:"storage"` // disk size in bytes + PhysicalSectorSize uint32 `json:"physicalSectorSize"` // disk physical-Sector size in bytes + LogicalSectorSize uint32 `json:"logicalSectorSize"` // disk logical-sector size in bytes } // DiskDetails contains basic and static info of a disk type DiskDetails struct { - RotationRate uint16 `json: "rotationRate"` // Disk rotation speed if disk is not SSD - DriveType string `json: "driveType"` // DriveType represents the type of drive like SSD, HDD etc., + RotationRate uint16 `json:"rotationRate"` // Disk rotation speed if disk is not SSD + DriveType string `json:"driveType"` // DriveType represents the type of drive like SSD, HDD etc., Model string `json:"model"` // Model is model of disk Compliance string `json:"compliance"` // Implemented standards/specifications version such as SPC-1, SPC-2, etc Serial string `json:"serial"` // Serial is serial no of disk @@ -79,3 +81,8 @@ type Temperature struct { HighestTemperature int16 `json:"highestTemperature"` LowestTemperature int16 `json:"lowestTemperature"` } + +type Partition struct { + PartitionType string `json:"partitionType"` + FileSystemType string `json:"fileSystemType"` +} diff --git a/pkg/udev/common.go b/pkg/udev/common.go index 5a169771e..fa34703c1 100644 --- a/pkg/udev/common.go +++ b/pkg/udev/common.go @@ -32,32 +32,36 @@ import ( ) const ( - NDMPrefix = "disk-" // NDMPrefix used as disk's uuid prefix - UDEV_SUBSYSTEM = "block" // udev to filter this device type - UDEV_SYSTEM = "disk" // used to filter devices other than disk which udev tracks (eg. CD ROM) - UDEV_PATH = "DEVPATH" // udev attribute to get device path - UDEV_WWN = "ID_WWN" // udev attribute to get device WWN number - UDEV_SERIAL = "ID_SERIAL_SHORT" // udev attribute to get device serial number - UDEV_SERIAL_FULL = "ID_SERIAL" // udev attribute to get - separated vendor, model, serial - UDEV_BUS = "ID_BUS" // udev attribute to get bus name - UDEV_MODEL = "ID_MODEL" // udev attribute to get device model number - UDEV_VENDOR = "ID_VENDOR" // udev attribute to get device vendor details - UDEV_TYPE = "ID_TYPE" // udev attribute to get device type - UDEV_MAJOR = "MAJOR" // udev attribute to get device major no - UDEV_MINOR = "MINOR" // udev attribute to get device minor no - UDEV_UUID = "UDEV_UUID" // ndm attribute to get device uuid - UDEV_SYSPATH = "UDEV_SYSPATH" // udev attribute to get device syspath - UDEV_ACTION = "UDEV_ACTION" // udev attribute to get monitor device action - UDEV_ACTION_ADD = "add" // udev attribute constant for add action - UDEV_ACTION_REMOVE = "remove" // udev attribute constant for remove action - UDEV_DEVTYPE = "DEVTYPE" // udev attribute to get device device type ie - disk or part - UDEV_SOURCE = "udev" // udev source constant - UDEV_SYSPATH_PREFIX = "/sys/dev/block/" // udev syspath prefix - UDEV_DEVNAME = "DEVNAME" // udev attribute contain disk name given by kernel - UDEV_DEVLINKS = "DEVLINKS" // udev attribute contain devlinks of a disk - BY_ID_LINK = "by-id" // by-path devlink contains this string - BY_PATH_LINK = "by-path" // by-path devlink contains this string - LINK_ID_INDEX = 4 // this is used to get link index from dev link + NDMPrefix = "disk-" // NDMPrefix used as disk's uuid prefix + UDEV_SUBSYSTEM = "block" // udev to filter this device type + UDEV_SYSTEM = "disk" // used to filter devices other than disk which udev tracks (eg. CD ROM) + UDEV_PARTITION = "partition" // used to filter out partitions + UDEV_PATH = "DEVPATH" // udev attribute to get device path + UDEV_WWN = "ID_WWN" // udev attribute to get device WWN number + UDEV_SERIAL = "ID_SERIAL_SHORT" // udev attribute to get device serial number + UDEV_SERIAL_FULL = "ID_SERIAL" // udev attribute to get - separated vendor, model, serial + UDEV_BUS = "ID_BUS" // udev attribute to get bus name + UDEV_MODEL = "ID_MODEL" // udev attribute to get device model number + UDEV_VENDOR = "ID_VENDOR" // udev attribute to get device vendor details + UDEV_TYPE = "ID_TYPE" // udev attribute to get device type + UDEV_MAJOR = "MAJOR" // udev attribute to get device major no + UDEV_MINOR = "MINOR" // udev attribute to get device minor no + UDEV_UUID = "UDEV_UUID" // ndm attribute to get device uuid + UDEV_SYSPATH = "UDEV_SYSPATH" // udev attribute to get device syspath + UDEV_ACTION = "UDEV_ACTION" // udev attribute to get monitor device action + UDEV_ACTION_ADD = "add" // udev attribute constant for add action + UDEV_ACTION_REMOVE = "remove" // udev attribute constant for remove action + UDEV_DEVTYPE = "DEVTYPE" // udev attribute to get device device type ie - disk or part + UDEV_SOURCE = "udev" // udev source constant + UDEV_SYSPATH_PREFIX = "/sys/dev/block/" // udev syspath prefix + UDEV_DEVNAME = "DEVNAME" // udev attribute contain disk name given by kernel + UDEV_DEVLINKS = "DEVLINKS" // udev attribute contain devlinks of a disk + BY_ID_LINK = "by-id" // by-path devlink contains this string + BY_PATH_LINK = "by-path" // by-path devlink contains this string + LINK_ID_INDEX = 4 // this is used to get link index from dev link + UDEV_PARTITION_TYPE = "ID_PART_ENTRY_TYPE" // udev attribute to get partition type + UDEV_FS_TYPE = "ID_FS_TYPE" // file system type the partition + UDEV_FS_NONE = "None" // udev constant for no file system ) // UdevDiskDetails struct contain different attribute of disk. @@ -68,6 +72,7 @@ type UdevDiskDetails struct { Path string // Path is Path of a disk. ByIdDevLinks []string // ByIdDevLinks contains by-id devlinks ByPathDevLinks []string // ByPathDevLinks contains by-path devlinks + FileSystem string // FileSystem on the disk } // freeCharPtr frees c pointer @@ -78,6 +83,10 @@ func freeCharPtr(s *C.char) { //DiskInfoFromLibudev returns disk attribute extracted using libudev apicalls. func (device *UdevDevice) DiskInfoFromLibudev() UdevDiskDetails { devLinks := device.GetDevLinks() + fileSystem := device.GetPropertyValue(UDEV_FS_TYPE) + if len(fileSystem) == 0 { + fileSystem = UDEV_FS_NONE + } diskDetails := UdevDiskDetails{ Model: device.GetPropertyValue(UDEV_MODEL), Serial: device.GetPropertyValue(UDEV_SERIAL), @@ -85,6 +94,7 @@ func (device *UdevDevice) DiskInfoFromLibudev() UdevDiskDetails { Path: device.GetPropertyValue(UDEV_DEVNAME), ByIdDevLinks: devLinks[BY_ID_LINK], ByPathDevLinks: devLinks[BY_PATH_LINK], + FileSystem: fileSystem, } return diskDetails } @@ -124,6 +134,26 @@ func (device *UdevDevice) IsDisk() bool { return device.GetDevtype() == UDEV_SYSTEM } +// IsPartition return true if device is a partition +func (device *UdevDevice) IsParitition() bool { + return device.GetDevtype() == UDEV_PARTITION +} + +// GetFileSystemInfo returns filesystem type on disk/partition if it exists. +func (device *UdevDevice) GetFileSystemInfo() string { + fileSystem := device.GetPropertyValue(UDEV_FS_TYPE) + if len(fileSystem) == 0 { + fileSystem = UDEV_FS_NONE + } + return fileSystem +} + +// GetPartitionType returns the partition type of the partition, like DOS, lvm2 etc +func (device *UdevDevice) GetPartitionType() string { + partitionType := device.GetPropertyValue(UDEV_PARTITION_TYPE) + return partitionType +} + // GetSyspath returns syspath of a disk using syspath we can fell details // in diskInfo struct using udev probe func (device *UdevDevice) GetSyspath() string { diff --git a/pkg/udev/common_test.go b/pkg/udev/common_test.go index 641ac0cfb..8ab5c38f1 100644 --- a/pkg/udev/common_test.go +++ b/pkg/udev/common_test.go @@ -83,6 +83,7 @@ func TestDiskInfoFromLibudev(t *testing.T) { Path: diskDetails.DevNode, ByIdDevLinks: diskDetails.ByIdDevLinks, ByPathDevLinks: diskDetails.ByPathDevLinks, + FileSystem: diskDetails.FileSystem, } assert.Equal(t, expectedDiskDetails, device.DiskInfoFromLibudev()) tests := map[string]struct { diff --git a/pkg/udev/mockdata.go b/pkg/udev/mockdata.go index 21b33e3e4..95d4c0330 100644 --- a/pkg/udev/mockdata.go +++ b/pkg/udev/mockdata.go @@ -42,6 +42,7 @@ type MockOsDiskDetails struct { Vendor string Wwn string Uid string + FileSystem string ByIdDevLinks []string ByPathDevLinks []string } @@ -81,6 +82,7 @@ func MockDiskDetails() (MockOsDiskDetails, error) { diskDetails.Vendor = device.GetPropertyValue(UDEV_VENDOR) diskDetails.Wwn = device.GetPropertyValue(UDEV_WWN) diskDetails.Uid = device.GetUid() + diskDetails.FileSystem = UDEV_FS_NONE devLinks := device.GetDevLinks() diskDetails.ByIdDevLinks = devLinks[BY_ID_LINK] diskDetails.ByPathDevLinks = devLinks[BY_PATH_LINK]