Skip to content

Commit f608d27

Browse files
committed
feat(uuid): add partition table uuid support
1 parent 9fbcfa8 commit f608d27

File tree

9 files changed

+145
-17
lines changed

9 files changed

+145
-17
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"
@@ -38,6 +40,10 @@ const (
3840
ChangeEA EventAction = libudevwrapper.UDEV_ACTION_CHANGE
3941
)
4042

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

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

58-
isErrorDuringUpdate := false
64+
isNeedRescan := false
5965
erroredDevices := make([]string, 0)
6066

6167
// iterate through each block device and perform the add/update operation
@@ -82,9 +88,11 @@ func (pe *ProbeEvent) addBlockDeviceEvent(msg controller.EventMessage) {
8288
}
8389
err := pe.addBlockDevice(*device, bdAPIList)
8490
if err != nil {
85-
isErrorDuringUpdate = true
86-
erroredDevices = append(erroredDevices, device.DevPath)
87-
klog.Error(err)
91+
isNeedRescan = true
92+
if !errors.Is(err, ErrNeedRescan) {
93+
erroredDevices = append(erroredDevices, device.DevPath)
94+
klog.Error(err)
95+
}
8896
}
8997
} else {
9098
// if GPTBasedUUID is disabled and the device type is partition,
@@ -98,13 +106,13 @@ func (pe *ProbeEvent) addBlockDeviceEvent(msg controller.EventMessage) {
98106
existingBlockDeviceResource := pe.Controller.GetExistingBlockDeviceResource(bdAPIList, deviceInfo.UUID)
99107
err := pe.Controller.PushBlockDeviceResource(existingBlockDeviceResource, deviceInfo)
100108
if err != nil {
101-
isErrorDuringUpdate = true
109+
isNeedRescan = true
102110
klog.Error(err)
103111
}
104112
}
105113
}
106114

107-
if isErrorDuringUpdate {
115+
if isNeedRescan {
108116
go Rescan(pe.Controller)
109117
}
110118
}

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: 16 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,30 @@ 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+
PartitionTableType: "gpt",
52+
PartitionTableUUID: fakePartitionTableUUID,
53+
},
54+
},
55+
wantUUID: blockdevice.BlockDevicePrefix + util.Hash(fakePartitionTableUUID),
56+
wantOk: true,
57+
},
4258
"deviceType-disk with WWN": {
4359
bd: blockdevice.BlockDevice{
4460
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: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ const (
5050
// ChangeDetection is used to enable detecting changes to
5151
// blockdevice size, filesystem, and mount-points.
5252
ChangeDetection Feature = "ChangeDetection"
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,14 +65,16 @@ var supportedFeatures = []Feature{
5965
APIService,
6066
UseOSDisk,
6167
ChangeDetection,
68+
PartitionTableUUID,
6269
}
6370

6471
// defaultFeatureGates is the default features that will be applied to the application
6572
var defaultFeatureGates = map[Feature]bool{
66-
GPTBasedUUID: true,
67-
APIService: false,
68-
UseOSDisk: false,
69-
ChangeDetection: false,
73+
GPTBasedUUID: true,
74+
APIService: false,
75+
UseOSDisk: false,
76+
ChangeDetection: false,
77+
PartitionTableUUID: false,
7078
}
7179

7280
// featureFlag is a map representing the flag and its state

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)