|
|
|
package cluster
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"net/netip"
|
|
|
|
"sort"
|
|
|
|
|
|
|
|
"darvaza.org/core"
|
|
|
|
"github.com/gofrs/uuid/v5"
|
|
|
|
|
|
|
|
"git.jpi.io/amery/jpictl/pkg/ceph"
|
|
|
|
)
|
|
|
|
|
|
|
|
// GetCephFSID returns our Ceph's FSID
|
|
|
|
func (m *Cluster) GetCephFSID() (uuid.UUID, error) {
|
|
|
|
if core.IsZero(m.CephFSID) {
|
|
|
|
// generate one
|
|
|
|
v, err := uuid.NewV4()
|
|
|
|
if err != nil {
|
|
|
|
return uuid.Nil, err
|
|
|
|
}
|
|
|
|
m.CephFSID = v
|
|
|
|
}
|
|
|
|
return m.CephFSID, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetCephConfig reads the ceph.conf file
|
|
|
|
func (m *Cluster) GetCephConfig() (*ceph.Config, error) {
|
|
|
|
data, err := m.ReadFile("ceph.conf")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
r := bytes.NewReader(data)
|
|
|
|
return ceph.NewConfigFromReader(r)
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteCephConfig writes the ceph.conf file
|
|
|
|
func (m *Cluster) WriteCephConfig(cfg *ceph.Config) error {
|
|
|
|
f, err := m.CreateTruncFile("ceph.conf")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
_, err = cfg.WriteTo(f)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GenCephConfig prepares a ceph.Config using the cluster information
|
|
|
|
func (m *Cluster) GenCephConfig() (*ceph.Config, error) {
|
|
|
|
fsid, err := m.GetCephFSID()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg := &ceph.Config{
|
|
|
|
Global: ceph.GlobalConfig{
|
|
|
|
FSID: fsid,
|
|
|
|
ClusterNetwork: netip.PrefixFrom(
|
|
|
|
netip.AddrFrom4([4]byte{10, 0, 0, 0}),
|
|
|
|
8,
|
|
|
|
),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
m.ForEachZone(func(z *Zone) bool {
|
|
|
|
for _, p := range z.GetCephMonitors() {
|
|
|
|
addr := p.RingOneAddress()
|
|
|
|
|
|
|
|
cfg.Global.Monitors = append(cfg.Global.Monitors, p.Name)
|
|
|
|
cfg.Global.MonitorsAddr = append(cfg.Global.MonitorsAddr, addr)
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
|
|
|
return cfg, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetCephMonitors returns the set of Ceph monitors on
|
|
|
|
// the zone
|
|
|
|
func (z *Zone) GetCephMonitors() Machines {
|
|
|
|
var mons Machines
|
|
|
|
var first, second *Machine
|
|
|
|
|
|
|
|
z.ForEachMachine(func(p *Machine) bool {
|
|
|
|
switch {
|
|
|
|
case p.CephMonitor:
|
|
|
|
// it is a monitor
|
|
|
|
mons = append(mons, p)
|
|
|
|
case len(mons) > 0:
|
|
|
|
// zone has a monitor
|
|
|
|
case first == nil && !p.IsGateway():
|
|
|
|
// first option for monitor
|
|
|
|
first = p
|
|
|
|
case second == nil:
|
|
|
|
// second option for monitor
|
|
|
|
second = p
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case len(mons) > 0:
|
|
|
|
// ready
|
|
|
|
case first != nil:
|
|
|
|
// make first option our monitor
|
|
|
|
first.CephMonitor = true
|
|
|
|
mons = append(mons, first)
|
|
|
|
case second != nil:
|
|
|
|
// make second option our monitor
|
|
|
|
second.CephMonitor = true
|
|
|
|
mons = append(mons, second)
|
|
|
|
default:
|
|
|
|
// zone without machines??
|
|
|
|
panic("unreachable")
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Sort(mons)
|
|
|
|
return mons
|
|
|
|
}
|