Skip to content

Commit b3aeeca

Browse files
committed
incusd/instance/drivers: say less about rbd to qemu
QEMU interfaces with librados for providing Ceph RBD support and as such already has quite robust cluster discovery abilities. Instead of telling QEMU everything it could possibly want to know and risking telling it something wrong, tell it what it needs to know (user, pool, image). Then QEMU can almost certainly do a better and faster job of collecting the necessary information for initiating a cluster connection. Signed-off-by: Michael 'ASAP' Weinrich <[email protected]>
1 parent c137b63 commit b3aeeca

File tree

2 files changed

+37
-75
lines changed

2 files changed

+37
-75
lines changed

internal/server/device/device_utils_disk.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,36 @@ const RBDFormatPrefix = "rbd"
2929
// RBDFormatSeparator is the field separate used in disk paths for RBD devices.
3030
const RBDFormatSeparator = " "
3131

32-
// DiskParseRBDFormat parses an rbd formatted string, and returns the pool name, volume name, and list of options.
33-
func DiskParseRBDFormat(rbd string) (string, string, []string, error) {
34-
if !strings.HasPrefix(rbd, fmt.Sprintf("%s%s", RBDFormatPrefix, RBDFormatSeparator)) {
35-
return "", "", nil, fmt.Errorf("Invalid rbd format, missing prefix")
36-
}
37-
38-
fields := strings.SplitN(rbd, RBDFormatSeparator, 3)
39-
if len(fields) != 3 {
40-
return "", "", nil, fmt.Errorf("Invalid rbd format, invalid number of fields")
41-
}
42-
43-
opts := fields[2]
32+
// DiskParseRBDFormat parses an rbd formatted string, and returns the pool name, volume name, and map of options.
33+
func DiskParseRBDFormat(rbd string) (pool string, volume string, opts map[string]string, err error) {
34+
// FIXME: This does not handle escaped strings
35+
// Remove and check the prefix
36+
prefix, rbd, _ := strings.Cut(rbd, RBDFormatSeparator)
37+
if prefix != RBDFormatPrefix {
38+
return "", "", nil, fmt.Errorf("Invalid rbd format, wrong prefix: %q", prefix)
39+
}
40+
41+
// Split the path and options
42+
path, rawOpts, _ := strings.Cut(rbd, RBDFormatSeparator)
43+
44+
// Check for valid RBD path
45+
pool, volume, validPath := strings.Cut(path, "/")
46+
if !validPath {
47+
return "", "", nil, fmt.Errorf("Invalid rbd format, missing pool and/or volume: %q", path)
48+
}
49+
50+
// Parse options
51+
opts = make(map[string]string)
52+
for _, o := range strings.Split(rawOpts, ":") {
53+
k, v, isValid := strings.Cut(o, "=")
54+
if !isValid {
55+
return "", "", nil, fmt.Errorf("Invalid rbd format, bad option: %q", o)
56+
}
4457

45-
fields = strings.SplitN(fields[1], "/", 2)
46-
if len(fields) != 2 {
47-
return "", "", nil, fmt.Errorf("Invalid rbd format, invalid pool or volume")
58+
opts[k] = v
4859
}
4960

50-
return fields[0], fields[1], strings.Split(opts, ":"), nil
61+
return pool, volume, opts, nil
5162
}
5263

5364
// DiskGetRBDFormat returns a rbd formatted string with the given values.
@@ -58,7 +69,6 @@ func DiskGetRBDFormat(clusterName string, userName string, poolName string, volu
5869
opts := []string{
5970
fmt.Sprintf("id=%s", optEscaper.Replace(userName)),
6071
fmt.Sprintf("pool=%s", optEscaper.Replace(poolName)),
61-
fmt.Sprintf("conf=/etc/ceph/%s.conf", optEscaper.Replace(clusterName)),
6272
}
6373

6474
return fmt.Sprintf("%s%s%s/%s%s%s", RBDFormatPrefix, RBDFormatSeparator, optEscaper.Replace(poolName), optEscaper.Replace(volumeName), RBDFormatSeparator, strings.Join(opts, ":"))

internal/server/instance/drivers/driver_qemu.go

Lines changed: 10 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -4200,7 +4200,7 @@ func (d *qemu) addDriveConfig(qemuDev map[string]any, bootIndexes map[string]int
42004200
} else if isRBDImage {
42014201
blockDev["driver"] = "rbd"
42024202

4203-
_, volName, opts, err := device.DiskParseRBDFormat(driveConf.DevPath)
4203+
poolName, volName, opts, err := device.DiskParseRBDFormat(driveConf.DevPath)
42044204
if err != nil {
42054205
return nil, fmt.Errorf("Failed parsing rbd string: %w", err)
42064206
}
@@ -4225,68 +4225,20 @@ func (d *qemu) addDriveConfig(qemuDev map[string]any, bootIndexes map[string]int
42254225
vol := storageDrivers.NewVolume(nil, "", volumeType, rbdContentType, volumeName, nil, nil)
42264226
rbdImageName := storageDrivers.CephGetRBDImageName(vol, "", false)
42274227

4228-
// Parse the options (ceph credentials).
4229-
userName := storageDrivers.CephDefaultUser
4230-
clusterName := storageDrivers.CephDefaultCluster
4231-
poolName := ""
4232-
4233-
for _, option := range opts {
4234-
fields := strings.Split(option, "=")
4235-
if len(fields) != 2 {
4236-
return nil, fmt.Errorf("Unexpected volume rbd option %q", option)
4237-
}
4238-
4239-
if fields[0] == "id" {
4240-
userName = fields[1]
4241-
} else if fields[0] == "pool" {
4242-
poolName = fields[1]
4243-
} else if fields[0] == "conf" {
4244-
baseName := filepath.Base(fields[1])
4245-
clusterName = strings.TrimSuffix(baseName, ".conf")
4228+
// scan & pass through options
4229+
blockDev["pool"] = poolName
4230+
blockDev["image"] = rbdImageName
4231+
for key, val := range opts {
4232+
// We use 'id' where qemu uses 'user'
4233+
if key == "id" {
4234+
blockDev["user"] = val
4235+
} else {
4236+
blockDev[key] = val
42464237
}
42474238
}
42484239

4249-
if poolName == "" {
4250-
return nil, fmt.Errorf("Missing pool name")
4251-
}
4252-
42534240
// The aio option isn't available when using the rbd driver.
42544241
delete(blockDev, "aio")
4255-
blockDev["pool"] = poolName
4256-
blockDev["image"] = rbdImageName
4257-
blockDev["user"] = userName
4258-
blockDev["server"] = []map[string]string{}
4259-
4260-
// Derference ceph config path.
4261-
cephConfPath := fmt.Sprintf("/etc/ceph/%s.conf", clusterName)
4262-
target, err := filepath.EvalSymlinks(cephConfPath)
4263-
if err == nil {
4264-
cephConfPath = target
4265-
}
4266-
4267-
blockDev["conf"] = cephConfPath
4268-
4269-
// Setup the Ceph cluster config (monitors and keyring).
4270-
monitors, err := storageDrivers.CephMonitors(clusterName)
4271-
if err != nil {
4272-
return nil, err
4273-
}
4274-
4275-
for _, monitor := range monitors {
4276-
idx := strings.LastIndex(monitor, ":")
4277-
host := monitor[:idx]
4278-
port := monitor[idx+1:]
4279-
4280-
blockDev["server"] = append(blockDev["server"].([]map[string]string), map[string]string{
4281-
"host": strings.Trim(host, "[]"),
4282-
"port": port,
4283-
})
4284-
}
4285-
4286-
rbdSecret, err = storageDrivers.CephKeyring(clusterName, userName)
4287-
if err != nil {
4288-
return nil, err
4289-
}
42904242
}
42914243

42924244
readonly := slices.Contains(driveConf.Opts, "ro")

0 commit comments

Comments
 (0)