Skip to content

Commit 58677e5

Browse files
committed
Merge branch '285-determine-pool-name' into 'master'
feat: extract pool name while automatic detection (#285) Closes #285 See merge request postgres-ai/database-lab!322
2 parents cad8c27 + e4b1b00 commit 58677e5

File tree

5 files changed

+94
-6
lines changed

5 files changed

+94
-6
lines changed

pkg/services/provision/docker/docker_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func TestVolumesBuilding(t *testing.T) {
4242
CloneName: "dblab_clone_6000",
4343
Pool: resources.Pool{
4444
Name: "dblab_pool",
45+
PoolDirName: "dblab_pool",
4546
MountDir: "/var/lib/dblab/",
4647
CloneSubDir: "clones",
4748
DataSubDir: "data",

pkg/services/provision/pool/pool_manager.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"gitlab.com/postgres-ai/database-lab/v2/pkg/retrieval/engine/postgres/tools"
2020
"gitlab.com/postgres-ai/database-lab/v2/pkg/services/provision/resources"
2121
"gitlab.com/postgres-ai/database-lab/v2/pkg/services/provision/runners"
22+
"gitlab.com/postgres-ai/database-lab/v2/pkg/services/provision/thinclones/zfs"
2223
)
2324

2425
const (
@@ -181,6 +182,8 @@ func (pm *Manager) examineEntries(entries []os.FileInfo) (map[string]FSManager,
181182
fsManagers := make(map[string]FSManager)
182183
poolList := &list.List{}
183184

185+
poolMappings := make(map[string]string)
186+
184187
for _, entry := range entries {
185188
if !entry.IsDir() {
186189
continue
@@ -204,6 +207,7 @@ func (pm *Manager) examineEntries(entries []os.FileInfo) (map[string]FSManager,
204207
pool := &resources.Pool{
205208
Mode: fsType,
206209
Name: entry.Name(),
210+
PoolDirName: entry.Name(),
207211
MountDir: pm.cfg.MountDir,
208212
CloneSubDir: pm.cfg.CloneSubDir,
209213
DataSubDir: pm.cfg.DataSubDir,
@@ -223,6 +227,21 @@ func (pm *Manager) examineEntries(entries []os.FileInfo) (map[string]FSManager,
223227
log.Msg(pool.DSA.String())
224228
}
225229

230+
// A custom pool name is not available for LVM.
231+
if fsType == ZFS {
232+
if len(poolMappings) == 0 {
233+
poolMappings, err = zfs.PoolMappings(pm.runner, pm.cfg.MountDir, pm.cfg.PreSnapshotSuffix)
234+
if err != nil {
235+
log.Msg("failed to get pool mappings:", err.Error())
236+
continue
237+
}
238+
}
239+
240+
if poolName, ok := poolMappings[entry.Name()]; ok {
241+
pool.Name = poolName
242+
}
243+
}
244+
226245
fsm, err := NewManager(pm.runner, ManagerConfig{
227246
Pool: pool,
228247
PreSnapshotSuffix: pm.cfg.PreSnapshotSuffix,
@@ -232,8 +251,7 @@ func (pm *Manager) examineEntries(entries []os.FileInfo) (map[string]FSManager,
232251
continue
233252
}
234253

235-
// TODO(akartasov): extract pool name.
236-
fsManagers[entry.Name()] = fsm
254+
fsManagers[pool.Name] = fsm
237255

238256
front := poolList.Front()
239257
if front == nil || front.Value == nil || fsManagers[front.Value.(string)].Pool().DSA.Before(pool.DSA) {

pkg/services/provision/resources/pool.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type Pool struct {
1616
Name string
1717
Mode string
1818
DSA time.Time
19+
PoolDirName string
1920
MountDir string
2021
CloneSubDir string
2122
DataSubDir string
@@ -40,12 +41,12 @@ func (p Pool) SetDSA(dsa time.Time) {
4041

4142
// DataDir returns a path to the data directory of the storage pool.
4243
func (p Pool) DataDir() string {
43-
return path.Join(p.MountDir, p.Name, p.DataSubDir)
44+
return path.Join(p.MountDir, p.PoolDirName, p.DataSubDir)
4445
}
4546

4647
// SocketDir returns a path to the sockets directory of the storage pool.
4748
func (p Pool) SocketDir() string {
48-
return path.Join(p.MountDir, p.Name, p.SocketSubDir)
49+
return path.Join(p.MountDir, p.PoolDirName, p.SocketSubDir)
4950
}
5051

5152
// ObserverDir returns a path to the observer directory of the storage pool.
@@ -55,12 +56,12 @@ func (p Pool) ObserverDir(port uint) string {
5556

5657
// ClonesDir returns a path to the clones directory of the storage pool.
5758
func (p Pool) ClonesDir() string {
58-
return path.Join(p.MountDir, p.Name, p.CloneSubDir)
59+
return path.Join(p.MountDir, p.PoolDirName, p.CloneSubDir)
5960
}
6061

6162
// ClonePath returns a path to the initialized clone directory.
6263
func (p Pool) ClonePath(port uint) string {
63-
return path.Join(p.MountDir, p.Name, p.CloneSubDir, util.GetCloneName(port), p.DataSubDir)
64+
return path.Join(p.MountDir, p.PoolDirName, p.CloneSubDir, util.GetCloneName(port), p.DataSubDir)
6465
}
6566

6667
// SocketCloneDir returns a path to the socket clone directory.

pkg/services/provision/thinclones/zfs/zfs.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package zfs
77

88
import (
99
"fmt"
10+
"path"
1011
"strconv"
1112
"strings"
1213
"time"
@@ -655,3 +656,45 @@ func (z *ListEntry) setDataStateAt(field string) error {
655656

656657
return nil
657658
}
659+
660+
// PoolMappings provides a mapping of pool name and mount point directory.
661+
func PoolMappings(runner runners.Runner, mountDir, preSnapshotSuffix string) (map[string]string, error) {
662+
listCmd := "zfs list -Ho name,mountpoint -t filesystem | grep -v " + preSnapshotSuffix
663+
664+
output, err := runner.Run(listCmd, false)
665+
if err != nil {
666+
return nil, errors.Wrap(err, "failed to list pools")
667+
}
668+
669+
return processMappingOutput(output, mountDir), nil
670+
}
671+
672+
func processMappingOutput(commandOutput, mountDir string) map[string]string {
673+
poolMappings := make(map[string]string)
674+
675+
lines := strings.Split(commandOutput, "\n")
676+
677+
for i := range lines {
678+
fields := strings.Fields(lines[i])
679+
680+
const poolFieldsNum = 2
681+
682+
if len(fields) < poolFieldsNum {
683+
log.Dbg("Mapping fields not found: ", fields)
684+
continue
685+
}
686+
687+
// Select pools from the first nested level.
688+
trimPrefix := strings.TrimPrefix(fields[1], mountDir)
689+
poolDir := strings.Trim(trimPrefix, "/")
690+
baseDir := path.Base(fields[1])
691+
692+
if poolDir == "" || baseDir != poolDir {
693+
continue
694+
}
695+
696+
poolMappings[poolDir] = fields[0]
697+
}
698+
699+
return poolMappings
700+
}

pkg/services/provision/thinclones/zfs/zfs_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,28 @@ func TestExcludingBusySnapshots(t *testing.T) {
159159
assert.Equal(t, tc.result, excludeBusySnapshots(tc.snapshotList))
160160
}
161161
}
162+
163+
func TestProcessingMappingOutput(t *testing.T) {
164+
out := `pgclusters /var/lib/postgresql/pools
165+
pgclusters/dblab /var/lib/postgresql/pools/dblab
166+
pgclusters/pgcluster1 /var/lib/postgresql/pools/pgcluster1
167+
pgclusters/pgcluster2 /var/lib/postgresql/pools/pgcluster2
168+
pgclusters/pgcluster5 /var/lib/postgresql/pools/pgcluster5/data
169+
datastore /var/lib/postgresql/pools/datastore
170+
datastore/clone_pre_20210729130000 /var/lib/postgresql/pools/datastore/clones/clone_pre_20210729130000
171+
datastore/dblab_clone_6000 /var/lib/postgresql/pools/datastore/clones/dblab_clone_6000
172+
datastore/dblab_clone_6001 /var/lib/postgresql/pools/datastore/clones/dblab_clone_6001
173+
poolnext /var/lib/postgresql/pools/pool5`
174+
mountDir := "/var/lib/postgresql/pools"
175+
expected := map[string]string{
176+
"dblab": "pgclusters/dblab",
177+
"pgcluster1": "pgclusters/pgcluster1",
178+
"pgcluster2": "pgclusters/pgcluster2",
179+
"datastore": "datastore",
180+
"pool5": "poolnext",
181+
}
182+
183+
poolMappings := processMappingOutput(out, mountDir)
184+
assert.Equal(t, len(expected), len(poolMappings))
185+
assert.Equal(t, expected, poolMappings)
186+
}

0 commit comments

Comments
 (0)