You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
2.2 KiB
141 lines
2.2 KiB
package cluster |
|
|
|
import ( |
|
"encoding/json" |
|
"fmt" |
|
"os" |
|
|
|
"gopkg.in/yaml.v3" |
|
|
|
"git.jpi.io/amery/jpictl/pkg/rings" |
|
) |
|
|
|
func (m *Cluster) init(opts *ScanOptions) error { |
|
for _, fn := range []func(*ScanOptions) error{ |
|
m.initZones, |
|
m.initRegions, |
|
m.scanZoneIDs, |
|
m.scanSort, |
|
m.scanGateways, |
|
m.initCephMonitors, |
|
} { |
|
if err := fn(opts); err != nil { |
|
return err |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
func (m *Cluster) initZones(opts *ScanOptions) error { |
|
var err error |
|
|
|
sub, err := DirFS(m.BaseDir) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
m.dir = sub |
|
|
|
m.ForEachZone(func(z *Zone) bool { |
|
err = m.initZone(z, opts) |
|
return err != nil |
|
}) |
|
|
|
return err |
|
} |
|
|
|
func (m *Cluster) initZone(z *Zone, _ *ScanOptions) error { |
|
var hasMissing bool |
|
var lastMachineID rings.NodeID |
|
|
|
z.zones = m |
|
z.logger = m |
|
|
|
z.ForEachMachine(func(p *Machine) bool { |
|
p.zone = z |
|
p.logger = z |
|
|
|
switch { |
|
case p.ID == 0: |
|
hasMissing = true |
|
case p.ID > lastMachineID: |
|
lastMachineID = p.ID |
|
} |
|
|
|
return false |
|
}) |
|
|
|
if hasMissing { |
|
next := lastMachineID + 1 |
|
|
|
z.ForEachMachine(func(p *Machine) bool { |
|
if p.ID == 0 { |
|
p.ID, next = next, next+1 |
|
} |
|
|
|
return false |
|
}) |
|
} |
|
|
|
z.ForEachMachine(func(p *Machine) bool { |
|
p.Name = fmt.Sprintf("%s-%v", z.Name, p.ID) |
|
return false |
|
}) |
|
|
|
return nil |
|
} |
|
|
|
func decodeConfigData(data []byte) (out *Cluster, err error) { |
|
// try JSON first |
|
out = new(Cluster) |
|
err = json.Unmarshal(data, out) |
|
if err == nil { |
|
// good json |
|
return out, nil |
|
} else if _, ok := err.(*json.SyntaxError); !ok { |
|
// bad json |
|
return nil, err |
|
} |
|
|
|
out = new(Cluster) |
|
err = yaml.Unmarshal(data, out) |
|
if err != nil { |
|
// bad yaml too |
|
return nil, err |
|
} |
|
|
|
// good yaml |
|
return out, nil |
|
} |
|
|
|
// NewFromConfig loads the cluster data from the given file |
|
func NewFromConfig(filename string, opts ...ScanOption) (*Cluster, error) { |
|
var scanOptions ScanOptions |
|
|
|
data, err := os.ReadFile(filename) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
m, err := decodeConfigData(data) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
for _, opt := range opts { |
|
if err = opt(m, &scanOptions); err != nil { |
|
return nil, err |
|
} |
|
} |
|
|
|
if err = m.setScanDefaults(&scanOptions); err != nil { |
|
return nil, err |
|
} |
|
|
|
if err := m.init(&scanOptions); err != nil { |
|
return nil, err |
|
} |
|
|
|
return m, nil |
|
}
|
|
|