Skip to content

Commit 27508d1

Browse files
committed
feat(uuid): add partition table uuid support
1 parent 426eeaa commit 27508d1

File tree

9 files changed

+140
-13
lines changed

9 files changed

+140
-13
lines changed

cmd/ndm_daemonset/probe/addhandler.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
apis "github.com/openebs/node-disk-manager/api/v1alpha1"
2323
"github.com/openebs/node-disk-manager/blockdevice"
2424
"github.com/openebs/node-disk-manager/db/kubernetes"
25+
"github.com/openebs/node-disk-manager/pkg/features"
2526
"github.com/openebs/node-disk-manager/pkg/partition"
2627

2728
"k8s.io/apimachinery/pkg/api/errors"
@@ -111,18 +112,29 @@ func (pe *ProbeEvent) addBlockDevice(bd blockdevice.BlockDevice, bdAPIList *apis
111112
len(bd.DependentDevices.Holders) > 0 {
112113
klog.V(4).Infof("device: %s has holders/partitions. %+v", bd.DevPath, bd.DependentDevices)
113114
} else {
114-
klog.Infof("starting to create partition on device: %s", bd.DevPath)
115115
d := partition.Disk{
116116
DevPath: bd.DevPath,
117117
DiskSize: bd.Capacity.Storage,
118118
LogicalBlockSize: uint64(bd.DeviceAttributes.LogicalBlockSize),
119119
}
120-
if err := d.CreateSinglePartition(); err != nil {
121-
klog.Errorf("error creating partition for %s, %v", bd.DevPath, err)
122-
return err
120+
121+
if features.FeatureGates.IsEnabled(features.PartitionTableUUID) {
122+
klog.Infof("starting to create partition table on device: %s", bd.DevPath)
123+
if err := d.CreatePartitionTable(); err != nil {
124+
klog.Errorf("error create partition table for %s, %v", bd.DevPath, err)
125+
return err
126+
}
127+
klog.Infof("created new partition table in %s", bd.DevPath)
128+
return ErrNeedRescan
129+
} else {
130+
klog.Infof("starting to create partition on device: %s", bd.DevPath)
131+
if err := d.CreateSinglePartition(); err != nil {
132+
klog.Errorf("error creating partition for %s, %v", bd.DevPath, err)
133+
return err
134+
}
135+
klog.Infof("created new partition in %s", bd.DevPath)
136+
return nil
123137
}
124-
klog.Infof("created new partition in %s", bd.DevPath)
125-
return nil
126138
}
127139
} else {
128140
bd.UUID = uuid

cmd/ndm_daemonset/probe/eventhandler.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package probe
1818

1919
import (
20+
"errors"
21+
2022
"github.com/openebs/node-disk-manager/blockdevice"
2123
"github.com/openebs/node-disk-manager/cmd/ndm_daemonset/controller"
2224
"github.com/openebs/node-disk-manager/pkg/features"
@@ -37,6 +39,10 @@ const (
3739
MountEA EventAction = "mount-change"
3840
)
3941

42+
var (
43+
ErrNeedRescan = errors.New("need rescan")
44+
)
45+
4046
// ProbeEvent struct contain a copy of controller it will update disk resources
4147
type ProbeEvent struct {
4248
Controller *controller.Controller
@@ -54,7 +60,7 @@ func (pe *ProbeEvent) addBlockDeviceEvent(msg controller.EventMessage) {
5460

5561
isGPTBasedUUIDEnabled := features.FeatureGates.IsEnabled(features.GPTBasedUUID)
5662

57-
isErrorDuringUpdate := false
63+
isNeedRescan := false
5864
erroredDevices := make([]string, 0)
5965

6066
// iterate through each block device and perform the add/update operation
@@ -81,9 +87,11 @@ func (pe *ProbeEvent) addBlockDeviceEvent(msg controller.EventMessage) {
8187
}
8288
err := pe.addBlockDevice(*device, bdAPIList)
8389
if err != nil {
84-
isErrorDuringUpdate = true
85-
erroredDevices = append(erroredDevices, device.DevPath)
86-
klog.Error(err)
90+
isNeedRescan = true
91+
if !errors.Is(err, ErrNeedRescan) {
92+
erroredDevices = append(erroredDevices, device.DevPath)
93+
klog.Error(err)
94+
}
8795
}
8896
} else {
8997
// if GPTBasedUUID is disabled and the device type is partition,
@@ -97,13 +105,13 @@ func (pe *ProbeEvent) addBlockDeviceEvent(msg controller.EventMessage) {
97105
existingBlockDeviceResource := pe.Controller.GetExistingBlockDeviceResource(bdAPIList, deviceInfo.UUID)
98106
err := pe.Controller.PushBlockDeviceResource(existingBlockDeviceResource, deviceInfo)
99107
if err != nil {
100-
isErrorDuringUpdate = true
108+
isNeedRescan = true
101109
klog.Error(err)
102110
}
103111
}
104112
}
105113

106-
if isErrorDuringUpdate {
114+
if isNeedRescan {
107115
go Rescan(pe.Controller)
108116
}
109117
}

cmd/ndm_daemonset/probe/uuid.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"os"
2121

2222
"github.com/openebs/node-disk-manager/blockdevice"
23+
"github.com/openebs/node-disk-manager/pkg/blkid"
24+
"github.com/openebs/node-disk-manager/pkg/features"
2325
"github.com/openebs/node-disk-manager/pkg/util"
2426

2527
"k8s.io/klog"
@@ -84,6 +86,28 @@ func generateUUID(bd blockdevice.BlockDevice) (string, bool) {
8486
klog.Infof("device(%s) has a filesystem, using filesystem UUID: %s", bd.DevPath, bd.FSInfo.FileSystemUUID)
8587
uuidField = bd.FSInfo.FileSystemUUID
8688
ok = true
89+
case features.FeatureGates.IsEnabled(features.PartitionTableUUID) && len(bd.PartitionInfo.PartitionTableType) > 0:
90+
// if the host is CentOS 7, the `libblkid` version on host is `2.23`,
91+
// but the `PTUUID` tag was start to provide from `2.24`. This will cause
92+
// the udev cache fetched from host udevd will not contain env `ID_PART_TABLE_UUID`.
93+
// Fortunately, the `libblkid` version in our base container (ubuntu 16.04)
94+
// is `2.27.1`, will provide `PTUUID` tag, so we should fetch `PTUUID` from `blkid`.
95+
partUUID := ""
96+
if len(bd.PartitionInfo.PartitionTableUUID) == 0 {
97+
deviceIdentifier := blkid.DeviceIdentifier{DevPath: bd.DevPath}
98+
partUUID = deviceIdentifier.GetPartitionUUID()
99+
} else {
100+
partUUID = bd.PartitionInfo.PartitionTableUUID
101+
}
102+
103+
if len(partUUID) == 0 {
104+
klog.Errorf("device(%s) has a partition table, but can not get partition table uuid", bd.DevPath)
105+
break
106+
}
107+
108+
klog.Infof("device(%s) has a partition table, use partition table uuid: %s", bd.DevPath, partUUID)
109+
uuidField = partUUID
110+
ok = true
87111
}
88112

89113
if ok {

cmd/ndm_daemonset/probe/uuid_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"testing"
2222

2323
"github.com/openebs/node-disk-manager/blockdevice"
24+
"github.com/openebs/node-disk-manager/pkg/features"
2425
"github.com/openebs/node-disk-manager/pkg/util"
2526
"github.com/stretchr/testify/assert"
2627
)
@@ -30,15 +31,29 @@ func TestGenerateUUID(t *testing.T) {
3031
fakeSerial := "CT500MX500SSD1"
3132
fakeFileSystemUUID := "149108ca-f404-4556-a263-04943e6cb0b3"
3233
fakePartitionUUID := "065e2357-05"
34+
fakePartitionTableUUID := "6f479331-dad4-4ccb-b146-5c359c55399b"
3335
fakeLVM_DM_UUID := "LVM-j2xmqvbcVWBQK9Jdttte3CyeVTGgxtVV5VcCi3nxdwihZDxSquMOBaGL5eymBNvk"
3436
fakeCRYPT_DM_UUID := "CRYPT-LUKS1-f4608c76343d4b5badaf6651d32f752b-backup"
3537
loopDevicePath := "/dev/loop98"
3638
hostName, _ := os.Hostname()
39+
features.FeatureGates.SetFeatureFlag([]string{
40+
"GPTBasedUUID=1",
41+
"PartitionTableUUID=1",
42+
})
3743
tests := map[string]struct {
3844
bd blockdevice.BlockDevice
3945
wantUUID string
4046
wantOk bool
4147
}{
48+
"debiceType-disk with PartitionTableUUID": {
49+
bd: blockdevice.BlockDevice{
50+
PartitionInfo: blockdevice.PartitionInformation{
51+
PartitionTableUUID: fakePartitionTableUUID,
52+
},
53+
},
54+
wantUUID: blockdevice.BlockDevicePrefix + util.Hash(fakePartitionTableUUID),
55+
wantOk: true,
56+
},
4257
"deviceType-disk with WWN": {
4358
bd: blockdevice.BlockDevice{
4459
DeviceAttributes: blockdevice.DeviceAttribute{

deploy/helm/charts/templates/daemonset.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ spec:
3939
{{- if .Values.featureGates.enabled }}
4040
{{- if .Values.featureGates.GPTBasedUUID.enabled }}
4141
- --feature-gates={{ .Values.featureGates.GPTBasedUUID.featureGateFlag }}
42+
{{- if .Values.featureGates.PartitionTableUUID.enabled }}
43+
- --feature-gates={{ .Values.featureGates.PartitionTableUUID.featureGateFlag }}
44+
{{- end}}
4245
{{- end}}
4346
{{- if .Values.featureGates.APIService.enabled }}
4447
- --feature-gates={{ .Values.featureGates.APIService.featureGateFlag }}

deploy/helm/charts/values.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ featureGates:
122122
GPTBasedUUID:
123123
enabled: true
124124
featureGateFlag: "GPTBasedUUID"
125+
PartitionTableUUID:
126+
enabled: false
127+
featureGateFlag: "PartitionTableUUID"
125128
APIService:
126129
enabled: false
127130
featureGateFlag: "APIService"

pkg/blkid/blkid.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import (
3030
)
3131

3232
const (
33-
fsTypeIdentifier = "TYPE"
33+
fsTypeIdentifier = "TYPE"
34+
partitionUUIDIdentifier = "PTUUID"
3435
)
3536

3637
type DeviceIdentifier struct {
@@ -54,3 +55,19 @@ func (di *DeviceIdentifier) GetOnDiskFileSystem() string {
5455

5556
return C.GoString(fstype)
5657
}
58+
59+
func (di *DeviceIdentifier) GetPartitionUUID() string {
60+
var blkidType *C.char
61+
blkidType = C.CString(partitionUUIDIdentifier)
62+
defer C.free(unsafe.Pointer(blkidType))
63+
64+
var device *C.char
65+
device = C.CString(di.DevPath)
66+
defer C.free(unsafe.Pointer(device))
67+
68+
var ptuuid *C.char
69+
ptuuid = C.blkid_get_tag_value(nil, blkidType, device)
70+
defer C.free(unsafe.Pointer(ptuuid))
71+
72+
return C.GoString(ptuuid)
73+
}

pkg/features/features.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ const (
5050
// MountChangeDetection feature flag is used to enable/disable
5151
// mount point and fs type change detection for block devices
5252
MountChangeDetection = "MountChangeDetection"
53+
54+
// PartitionTableUUID feature flag is used to enable use a
55+
// partition table uuid instead of create partition described in
56+
// https://github.com/openebs/node-disk-manager/issues/621 .
57+
// This feature must enabled with GPTBasedUUID.
58+
PartitionTableUUID Feature = "PartitionTableUUID"
5359
)
5460

5561
// supportedFeatures is the list of supported features. This is used while parsing the
@@ -59,11 +65,13 @@ var supportedFeatures = []Feature{
5965
APIService,
6066
UseOSDisk,
6167
MountChangeDetection,
68+
PartitionTableUUID,
6269
}
6370

6471
// defaultFeatureGates is the default features that will be applied to the application
6572
var defaultFeatureGates = map[Feature]bool{
6673
GPTBasedUUID: true,
74+
PartitionTableUUID: false,
6775
APIService: false,
6876
UseOSDisk: false,
6977
MountChangeDetection: false,

pkg/partition/partition.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,40 @@ func (d *Disk) CreateSinglePartition() error {
164164
klog.Infof("created a single partition on disk %s", d.DevPath)
165165
return nil
166166
}
167+
168+
// CreatePartitionTable create a GPT header on the disk
169+
func (d *Disk) CreatePartitionTable() error {
170+
fd, err := diskfs.Open(d.DevPath)
171+
if err != nil {
172+
return fmt.Errorf("error opening disk fd for disk %s: %v", d.DevPath, err)
173+
}
174+
d.disk = fd
175+
176+
// check for any existing partition table on the disk
177+
if _, err := d.disk.GetPartitionTable(); err == nil {
178+
klog.Errorf("aborting partition creation, disk %s already contains a known partition table", d.DevPath)
179+
return fmt.Errorf("disk %s contains a partition table, cannot create a new partition table", d.DevPath)
180+
}
181+
182+
// check for any existing filesystem on the disk
183+
deviceIdentifier := blkid.DeviceIdentifier{
184+
DevPath: d.DevPath,
185+
}
186+
if fs := deviceIdentifier.GetOnDiskFileSystem(); len(fs) != 0 {
187+
klog.Errorf("aborting partition creation, disk %s contains a known filesystem: %s", d.DevPath, fs)
188+
return fmt.Errorf("disk %s contains a known filesyste: %s, cannot create a partition table", d.DevPath, fs)
189+
}
190+
191+
err = d.createPartitionTable()
192+
if err != nil {
193+
klog.Error("partition table initialization failed")
194+
return err
195+
}
196+
197+
err = d.disk.Partition(d.table)
198+
if err != nil {
199+
return fmt.Errorf("unable to create/write partition table. %v", err)
200+
}
201+
klog.Infof("created partition table on disk %s", d.DevPath)
202+
return nil
203+
}

0 commit comments

Comments
 (0)