-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: specify an ovn underlay network through MicroOVN #361
Changes from all commits
d8f50ce
dd9dbad
b773257
83ae28a
935c289
b9e97dd
f3f2c98
0e153d1
468b4a4
ecdfb61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ type Preseed struct { | |
type System struct { | ||
Name string `yaml:"name"` | ||
UplinkInterface string `yaml:"ovn_uplink_interface"` | ||
UnderlayIP string `yaml:"underlay_ip"` | ||
Storage InitStorage `yaml:"storage"` | ||
} | ||
|
||
|
@@ -220,6 +221,7 @@ func (c *initConfig) RunPreseed(cmd *cobra.Command) error { | |
// validate validates the unmarshaled preseed input. | ||
func (p *Preseed) validate(name string, bootstrap bool) error { | ||
uplinkCount := 0 | ||
underlayCount := 0 | ||
directCephCount := 0 | ||
directLocalCount := 0 | ||
localInit := false | ||
|
@@ -241,6 +243,15 @@ func (p *Preseed) validate(name string, bootstrap bool) error { | |
uplinkCount++ | ||
} | ||
|
||
if system.UnderlayIP != "" { | ||
_, _, err := net.ParseCIDR(system.UnderlayIP) | ||
if err != nil { | ||
return fmt.Errorf("Invalid underlay IP: %w", err) | ||
} | ||
|
||
underlayCount++ | ||
} | ||
|
||
if len(system.Storage.Ceph) > 0 { | ||
directCephCount++ | ||
} | ||
|
@@ -270,6 +281,11 @@ func (p *Preseed) validate(name string, bootstrap bool) error { | |
return fmt.Errorf("Some systems are missing an uplink interface") | ||
} | ||
|
||
containsUnderlay := underlayCount > 0 | ||
if containsUnderlay && underlayCount < len(p.Systems) { | ||
return fmt.Errorf("Some systems are missing an underlay interface") | ||
} | ||
|
||
containsLocalStorage = directLocalCount > 0 | ||
if containsLocalStorage && directLocalCount < len(p.Systems) && len(p.Storage.Local) == 0 { | ||
return fmt.Errorf("Some systems are missing local storage disks") | ||
|
@@ -484,10 +500,15 @@ func (p *Preseed) Parse(s *service.Handler, c *initConfig) (map[string]InitSyste | |
|
||
lxd := s.Services[types.LXD].(*service.LXDService) | ||
ifaceByPeer := map[string]string{} | ||
ovnUnderlayNeeded := false | ||
for _, cfg := range p.Systems { | ||
if cfg.UplinkInterface != "" { | ||
ifaceByPeer[cfg.Name] = cfg.UplinkInterface | ||
} | ||
|
||
if cfg.UnderlayIP != "" { | ||
ovnUnderlayNeeded = true | ||
} | ||
} | ||
|
||
localInfo, err := s.CollectSystemInformation(context.Background(), mdns.ServerInfo{Name: c.name, Address: c.address}) | ||
|
@@ -498,7 +519,7 @@ func (p *Preseed) Parse(s *service.Handler, c *initConfig) (map[string]InitSyste | |
// If an uplink interface was explicitly chosen, we will try to set up an OVN network. | ||
explicitOVN := len(ifaceByPeer) > 0 | ||
|
||
cephInterfaces := map[string]map[string]service.CephDedicatedInterface{} | ||
cephInterfaces := map[string]map[string]service.DedicatedInterface{} | ||
for _, system := range c.systems { | ||
uplinkIfaces, cephIfaces, _, err := lxd.GetNetworkInterfaces(context.Background(), system.ServerInfo.Name, system.ServerInfo.Address, system.ServerInfo.AuthSecret) | ||
if err != nil { | ||
|
@@ -517,7 +538,7 @@ func (p *Preseed) Parse(s *service.Handler, c *initConfig) (map[string]InitSyste | |
|
||
for ifaceName, iface := range cephIfaces { | ||
if cephInterfaces[system.ServerInfo.Name] == nil { | ||
cephInterfaces[system.ServerInfo.Name] = map[string]service.CephDedicatedInterface{} | ||
cephInterfaces[system.ServerInfo.Name] = map[string]service.DedicatedInterface{} | ||
} | ||
|
||
cephInterfaces[system.ServerInfo.Name][ifaceName] = iface | ||
|
@@ -542,6 +563,58 @@ func (p *Preseed) Parse(s *service.Handler, c *initConfig) (map[string]InitSyste | |
|
||
c.systems[peer] = system | ||
} | ||
|
||
// Check the preseed underlay network configuration against the available ips. | ||
if ovnUnderlayNeeded { | ||
canOVNUnderlay := true | ||
for peer, system := range c.state { | ||
if len(system.AvailableOVNInterfaces) == 0 { | ||
fmt.Printf("Not enough interfaces available on %s to create an underlay network, skipping\n", peer) | ||
canOVNUnderlay = false | ||
break | ||
} | ||
} | ||
Comment on lines
+570
to
+576
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
if canOVNUnderlay { | ||
// TODO: call `s.Services[types.MicroOVN].(*service.OVNService).SupportsFeature(context.Background(), "custom_encapsulation_ip")` | ||
// when MicroCloud will be updated with microcluster/v2 | ||
underlays := make(map[string]string, len(p.Systems)) | ||
for _, sys := range p.Systems { | ||
underlays[sys.Name] = sys.UnderlayIP | ||
} | ||
|
||
underlayCount := 0 | ||
for _, sys := range p.Systems { | ||
for _, net := range c.state[sys.Name].AvailableOVNInterfaces { | ||
if len(net.Addresses) != 0 { | ||
for _, cidrAddr := range net.Addresses { | ||
if underlays[sys.Name] == cidrAddr { | ||
underlayCount = underlayCount + 1 | ||
goto out | ||
} | ||
} | ||
} | ||
} | ||
|
||
out: | ||
} | ||
|
||
if underlayCount != len(p.Systems) { | ||
return nil, fmt.Errorf("Failed to find all underlay IPs on the network") | ||
} | ||
|
||
// Apply the underlay IPs to the systems. | ||
for peer, system := range c.systems { | ||
ip, _, err := net.ParseCIDR(underlays[peer]) | ||
if err != nil { | ||
return nil, fmt.Errorf("Failed to parse underlay IP: %w", err) | ||
} | ||
Comment on lines
+608
to
+611
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The input is not a cidr, so this will fail. |
||
|
||
system.OVNGeneveAddr = ip.String() | ||
c.systems[peer] = system | ||
} | ||
} | ||
} | ||
} else { | ||
// Check if FAN networking is usable. | ||
fanUsable, _, err := service.FanNetworkUsable() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we only apply the underlay config during bootstrap/join. When running
microcloud add
ormicrocloud service add
, other nodes may not have underlay networking configured, so even though we present a list of every old and new cluster member, no config will change.I guess this means we also need a way to set the geneve address over the API.
We could get around this for now if we at least have a way to get the current underlay configuration. We could just skip configuration in the
add
cases if it was not previously configured duringinit
.