Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 55 additions & 4 deletions pkg/cluster/manager/deploy_volume_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package manager
import (
"bytes"
"fmt"
"strings"
"time"

"github.com/seaweedfs/seaweed-up/pkg/cluster/spec"
"github.com/seaweedfs/seaweed-up/pkg/disks"
"github.com/seaweedfs/seaweed-up/pkg/operator"
"github.com/seaweedfs/seaweed-up/scripts"
"strings"
)

func (m *Manager) DeployVolumeServer(masters []string, volumeServerSpec *spec.VolumeServerSpec, index int) error {
Expand Down Expand Up @@ -119,14 +121,22 @@ func (m *Manager) prepareUnmountedDisks(op operator.CommandOperator) error {
}
fmt.Printf("disks2: %+v\n", disks)

// format disk if no fstype
// format disk if no fstype, then resolve the resulting UUID so the fstab
// entry written below can mount by UUID instead of by device path.
for _, dev := range disks {
if dev.FilesystemType == "" {
info("mkfs " + dev.Path)
if err := m.sudo(op, fmt.Sprintf("mkfs.ext4 %s", dev.Path)); err != nil {
return fmt.Errorf("create file system on %s: %v", dev.Path, err)
}
}
if dev.UUID == "" {
uuid, err := m.probeDiskUUID(op, dev.Path)
if err != nil {
return fmt.Errorf("resolve UUID for %s: %v", dev.Path, err)
}
dev.UUID = uuid
}
}

// mount them
Expand All @@ -148,6 +158,7 @@ func (m *Manager) prepareUnmountedDisks(op operator.CommandOperator) error {

data := map[string]interface{}{
"DevicePath": dev.Path,
"DeviceUUID": dev.UUID,
"MountPoint": targetMountPoint,
}
prepareScript, err := scripts.RenderScript("prepare_disk.sh", data)
Expand All @@ -160,8 +171,8 @@ func (m *Manager) prepareUnmountedDisks(op operator.CommandOperator) error {
return fmt.Errorf("error received during upload mount script: %s", err)
}

info("mount " + dev.DeviceName + "...")
err = op.Execute(fmt.Sprintf("cat /tmp/mount_%s.sh | SUDO_PASS=\"%s\" sh -\n", dev.DeviceName, m.sudoPass))
info(fmt.Sprintf("mount %s (UUID=%s) at %s", dev.DeviceName, dev.UUID, targetMountPoint))
err = op.Execute(fmt.Sprintf("cat /tmp/mount_%s.sh | SUDO_PASS=%s sh -\n", dev.DeviceName, shellSingleQuote(m.sudoPass)))
if err != nil {
return fmt.Errorf("error received during mount: %s", err)
}
Expand All @@ -171,3 +182,43 @@ func (m *Manager) prepareUnmountedDisks(op operator.CommandOperator) error {

return nil
}

// probeDiskUUID reads the filesystem UUID of path via blkid. After mkfs the
// superblock is written but udev may not yet have re-read it, so we let it
// settle and retry a few times before giving up. blkid needs root to read
// raw block devices on most distros (and -p always needs root), so we wrap
// it the same way m.sudo does. Returning an error here aborts the deploy
// rather than writing a broken fstab entry that would leave the host unable
// to boot.
func (m *Manager) probeDiskUUID(op operator.CommandOperator, path string) (string, error) {
// Best-effort settle. Ignore errors — `udevadm` is missing on some
// minimal images and that's OK; the retry loop below will still pick
// up the UUID once it's available.
_ = m.sudo(op, "command -v udevadm >/dev/null 2>&1 && udevadm settle || true")

// -p bypasses the blkid cache and re-probes the superblock directly,
// which is what we want right after mkfs.
probeCmd := fmt.Sprintf("blkid -p -s UUID -o value %s", shellSingleQuote(path))
if m.sudoPass != "" {
probeCmd = fmt.Sprintf("echo %s | sudo -S %s", shellSingleQuote(m.sudoPass), probeCmd)
}

const attempts = 5
var lastErr error
for i := 0; i < attempts; i++ {
out, err := op.Output(probeCmd)
if err == nil {
uuid := strings.TrimSpace(string(out))
if uuid != "" {
return uuid, nil
}
} else {
lastErr = err
}
time.Sleep(500 * time.Millisecond)
}
if lastErr != nil {
return "", fmt.Errorf("blkid returned no UUID after %d attempts: %v", attempts, lastErr)
}
return "", fmt.Errorf("blkid returned no UUID after %d attempts", attempts)
}
17 changes: 13 additions & 4 deletions scripts/prepare_disk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,25 @@ setup_env() {

MOUNT_POINT={{.MountPoint}}
DEVICE_PATH={{.DevicePath}}
DEVICE_UUID={{.DeviceUUID}}
}

setup_mount() {

info "Setup Mount Point"
$SUDO mkdir -p -m 755 ${MOUNT_POINT}
info "add ${DEVICE_PATH} ${MOUNT_POINT} to fstab"
echo "${DEVICE_PATH} ${MOUNT_POINT} ext4 noatime 0 2" | $SUDO tee -a /etc/fstab
info "mount ${DEVICE_PATH} ${MOUNT_POINT}"
$SUDO mount ${DEVICE_PATH} ${MOUNT_POINT}
if grep -qE "^UUID=${DEVICE_UUID}[[:space:]]" /etc/fstab; then
info "UUID=${DEVICE_UUID} already in fstab; skipping append"
else
info "add UUID=${DEVICE_UUID} (${DEVICE_PATH}) ${MOUNT_POINT} to fstab"
echo "UUID=${DEVICE_UUID} ${MOUNT_POINT} ext4 noatime 0 2" | $SUDO tee -a /etc/fstab
fi
if mountpoint -q "${MOUNT_POINT}"; then
info "${MOUNT_POINT} already mounted; skipping mount"
else
info "mount ${DEVICE_PATH} (UUID=${DEVICE_UUID}) at ${MOUNT_POINT}"
$SUDO mount ${MOUNT_POINT}
fi

return 0
}
Expand Down