volume.go
65 lines1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package scaffold
import (
"fmt"
"log"
"congo.gg/pkg/platform"
)
func ensureVolume(p *platform.Platform, server *platform.Server, spec *VolumeSpec, region platform.Region) error {
if !SafeName(spec.Name) {
return fmt.Errorf("volume name contains invalid characters: %q (use alphanumeric, dash, underscore)", spec.Name)
}
if !SafePath(spec.Mount) {
return fmt.Errorf("volume mount path invalid: %q (must be absolute, no ..)", spec.Mount)
}
log.Printf(" Ensuring volume %s...", spec.Name)
vol, err := p.GetVolume(spec.Name)
if err == platform.ErrUnsupported {
// Metal provider: no cloud volumes, just ensure mount dir exists
log.Printf(" Using local disk for %s", spec.Name)
if _, err := server.SSH("mkdir", "-p", spec.Mount); err != nil {
return fmt.Errorf("create mount dir: %w", err)
}
return nil
}
isNew := err == platform.ErrNotFound
if isNew {
vol, err = p.CreateVolume(spec.Name, spec.Size, region)
if err != nil {
return fmt.Errorf("create volume: %w", err)
}
} else if err != nil {
return fmt.Errorf("get volume: %w", err)
}
if err := p.AttachVolume(vol.ID, server.ID); err != nil {
log.Printf(" Volume attach: %v (may already be attached)", err)
}
devicePath := fmt.Sprintf("/dev/disk/by-id/scsi-0DO_Volume_%s", spec.Name)
if isNew {
formatScript := fmt.Sprintf(`
for i in $(seq 1 30); do [ -e %s ] && break; sleep 1; done
if ! blkid %s >/dev/null 2>&1; then mkfs.ext4 %s; fi
`, devicePath, devicePath, devicePath)
if _, err := server.SSH("bash", "-c", formatScript); err != nil {
return fmt.Errorf("format volume: %w", err)
}
}
mountScript := fmt.Sprintf(`
mkdir -p %s
grep -qF "%s" /etc/fstab || echo "%s %s ext4 defaults,nofail,discard 0 2" >> /etc/fstab
mountpoint -q %s || mount %s || true
`, spec.Mount, spec.Name, devicePath, spec.Mount, spec.Mount, spec.Mount)
if _, err := server.SSH("bash", "-c", mountScript); err != nil {
return fmt.Errorf("mount volume: %w", err)
}
return nil
}