Skip to content

Commit

Permalink
microcloud/ask: Interactively configure a custom underlay network
Browse files Browse the repository at this point in the history
Signed-off-by: Gabriel Mougard <gabriel.mougard@canonical.com>
  • Loading branch information
gabrielmougard committed Apr 16, 2024
1 parent a9a8c19 commit 2f1ca9f
Showing 1 changed file with 113 additions and 6 deletions.
119 changes: 113 additions & 6 deletions microcloud/cmd/microcloud/ask.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,19 +599,21 @@ func (c *CmdControl) askNetwork(sh *service.Handler, systems map[string]InitSyst
infos = append(infos, system.ServerInfo)
}

allNetworks, err := sh.Services[types.LXD].(*service.LXDService).GetInterfaces(context.Background(), bootstrap, infos, service.UplinkInterface)
allNetworks, err := sh.Services[types.LXD].(*service.LXDService).GetInterfaces(context.Background(), bootstrap, infos, service.UnderlayInterface|service.UplinkInterface)
if err != nil {
return err
}

uplinkNetworks := make(map[string][]api.Network)
for peer, networks := range allNetworks {
for _, net := range networks {
_, ok := uplinkNetworks[peer]
if !ok {
uplinkNetworks[peer] = []api.Network{net.Network}
} else {
uplinkNetworks[peer] = append(uplinkNetworks[peer], net.Network)
if len(net.Addresses) == 0 {
_, ok := uplinkNetworks[peer]
if !ok {
uplinkNetworks[peer] = []api.Network{net.Network}
} else {
uplinkNetworks[peer] = append(uplinkNetworks[peer], net.Network)
}
}
}
}
Expand Down Expand Up @@ -832,5 +834,110 @@ func (c *CmdControl) askNetwork(sh *service.Handler, systems map[string]InitSyst
systems[sh.Name] = bootstrapSystem
}

// Underlay network selection table.
// Ask the user if they want an underlay network.
if bootstrap {
wantsDedicatedUnderlay, err := c.asker.AskBool("Configure dedicated underlay networking? (yes/no) [default=no]: ", "no")
if err != nil {
return err
}

if !wantsDedicatedUnderlay {
return nil
}
} else {
// If the bootstrapped node has an underlay network, then we don't need to ask. Else, return.
customUnderlayEnabled := false
for _, system := range systems {
if system.OVNGeneveAddr != "" {
customUnderlayEnabled = true
break
}
}

if !customUnderlayEnabled {
return nil
}
}

underlayNetworks := make(map[string][]service.NetworkWithAllocatedIPs)
for peer, networks := range allNetworks {
for _, net := range networks {
if len(net.Addresses) != 0 {
_, ok := underlayNetworks[peer]
if !ok {
underlayNetworks[peer] = []service.NetworkWithAllocatedIPs{net}
} else {
underlayNetworks[peer] = append(underlayNetworks[peer], net)
}
}
}
}

if len(underlayNetworks) != len(systems) {
fmt.Println("Not enough interfaces available to create an underlay network, skipping")
return nil
}

for peer, nets := range underlayNetworks {
if len(nets) == 0 {
fmt.Printf("Not enough interfaces available on %q to configure the underlay network, skipping\n", peer)
return nil
}
}

header = []string{"LOCATION", "IFACE", "TYPE", "IP ADDRESS (CIDR)"}
fmt.Println("Select exactly one network interface from each cluster member:")
data = [][]string{}
for peer, nets := range underlayNetworks {
for _, net := range nets {
for _, addr := range net.Addresses {
data = append(data, []string{peer, net.Network.Name, net.Network.Type, addr})
}
}
}

table = NewSelectableTable(header, data)
selected = map[string]string{}
c.askRetry("Retry selecting underlay network interfaces?", autoSetup, func() error {
err = table.Render(table.rows)
if err != nil {
return err
}

answers, err := table.GetSelections()
if err != nil {
return err
}

selected = map[string]string{}
for _, answer := range answers {
target := table.SelectionValue(answer, "LOCATION")
ipAddr := table.SelectionValue(answer, "IP ADDRESS (CIDR)")

if selected[target] != "" {
return fmt.Errorf("Failed to configure OVN underlay traffic: Selected more than one interface for target %q", target)
}

selected[target] = ipAddr
}

if len(selected) != len(underlayNetworks) {
return fmt.Errorf("Failed to configure OVN underlay traffic: Some peers don't have a selected interface")
}

return nil
})

for peer, ipAddr := range selected {
system := systems[peer]
ip, _, err := net.ParseCIDR(ipAddr)
if err != nil {
return err
}

system.OVNGeneveAddr = ip.String()
}

return nil
}

0 comments on commit 2f1ca9f

Please sign in to comment.