Skip to content

Commit

Permalink
microcloud/cmd/microcloud: Preseed logic to setup a dedicated Ceph ne…
Browse files Browse the repository at this point in the history
…twork

The added logic handle the bootstrapping and adding logic, when a
dedicated Ceph network has been required.

Signed-off-by: Gabriel Mougard <[email protected]>
  • Loading branch information
gabrielmougard committed Apr 3, 2024
1 parent 332351b commit 1c13735
Showing 1 changed file with 83 additions and 0 deletions.
83 changes: 83 additions & 0 deletions microcloud/cmd/microcloud/main_init_preseed.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
lxdAPI "github.com/canonical/lxd/shared/api"
"github.com/canonical/lxd/shared/filter"
"github.com/canonical/lxd/shared/units"
"github.com/canonical/lxd/shared/validate"
cephTypes "github.com/canonical/microceph/microceph/api/types"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
Expand All @@ -28,6 +29,7 @@ type Preseed struct {
LookupInterface string `yaml:"lookup_interface"`
Systems []System `yaml:"systems"`
OVN InitNetwork `yaml:"ovn"`
Ceph CephOptions `yaml:"ceph"`
Storage StorageFilter `yaml:"storage"`
}

Expand Down Expand Up @@ -58,6 +60,11 @@ type InitNetwork struct {
DNSServers string `yaml:"dns_servers"`
}

// CephOptions represents the structure of the ceph options in the preseed yaml.
type CephOptions struct {
Network string `yaml:"network"`
}

// StorageFilter separates the filters used for local and ceph disks.
type StorageFilter struct {
CephFS bool `yaml:"cephfs"`
Expand Down Expand Up @@ -240,6 +247,18 @@ func (p *Preseed) validate(name string, bootstrap bool) error {
return fmt.Errorf("Missing interface name for machine lookup")
}

usingCephNetwork := p.Ceph.Network != ""
if !containsCephStorage && usingCephNetwork {
return fmt.Errorf("Cannot specify ceph network without ceph storage disks")
}

if usingCephNetwork {
err = validate.IsNetwork(p.Ceph.Network)
if err != nil {
return fmt.Errorf("Invalid Ceph network subnet: %v", err)
}
}

usingOVN := p.OVN.IPv4Gateway != "" || p.OVN.IPv6Gateway != "" || containsUplinks
if bootstrap && usingOVN && len(p.Systems) < 3 {
return fmt.Errorf("At least 3 systems are required to configure distributed networking")
Expand Down Expand Up @@ -636,6 +655,70 @@ func (p *Preseed) Parse(s *service.Handler, bootstrap bool) (map[string]InitSyst
systems[peer] = system
}

if len(cephMachines) > 0 {
infos := make([]mdns.ServerInfo, 0, len(systems))
for _, system := range systems {
infos = append(infos, system.ServerInfo)
}

cephInterfaces, err := lxd.GetCephInterfaces(context.Background(), bootstrap, infos)
if err != nil {
return nil, err
}

// Initialize Ceph network if specified.
if p.Ceph.Network != "" && bootstrap {
validatedCephInterfacesData, err := lxd.ValidateCephInterfaces(p.Ceph.Network, cephInterfaces)
if err != nil {
return nil, err
}

if len(validatedCephInterfacesData) < len(systems) {
return nil, fmt.Errorf("not enough network interfaces found with an IP within the given CIDR subnet.\nYou need at least one interface of that kind per cluster member of the cluster")
} else {
bootstrapSystem := systems[s.Name]
bootstrapSystem.MicroCephNetworkSubnet = p.Ceph.Network
systems[s.Name] = bootstrapSystem
}
} else if !bootstrap {
// In case of new machines added to the cluster that will be part of an existing Ceph cluster,
// and if a dedicated Ceph cluster network has been configured, we need to ensure that the new machines
// have at least one network interface with an IP within the existing Ceph network subnet.
microCephService := s.Services[types.MicroCeph].(*service.CephService)
if microCephService == nil {
return nil, fmt.Errorf("failed to get MicroCeph service")
}

cephConfigs, err := microCephService.ClusterConfig(context.Background())
if err != nil {
return nil, err
}

// Read the Ceph network configuration from the existing Ceph cluster
cephNetworkSubnet := ""
for key, value := range cephConfigs {
if key == "cluster_network" {
err = validate.IsNetwork(value)
if err != nil {
return nil, fmt.Errorf("failed to parse the Ceph cluster network configuration from the existing Ceph cluster: %v", err)
}

cephNetworkSubnet = value
break
}
}

if cephNetworkSubnet == "" {
return nil, fmt.Errorf("failed to find the Ceph cluster network configuration from the existing Ceph cluster")
}

_, err = lxd.ValidateCephInterfaces(cephNetworkSubnet, cephInterfaces)
if err != nil {
return nil, err
}
}
}

// Check that the filters matched the correct amount of disks.
for _, filter := range p.Storage.Ceph {
if cephMatches[filter.Find] < filter.FindMin {
Expand Down

0 comments on commit 1c13735

Please sign in to comment.