|
1 | 1 | package main
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "net" |
4 | 5 | "testing"
|
5 | 6 |
|
6 | 7 | lxdAPI "github.com/canonical/lxd/shared/api"
|
| 8 | + "github.com/stretchr/testify/assert" |
7 | 9 |
|
8 | 10 | "github.com/canonical/microcloud/microcloud/multicast"
|
9 | 11 | "github.com/canonical/microcloud/microcloud/service"
|
@@ -226,3 +228,103 @@ func TestValidateSystemsMultiSystem(t *testing.T) {
|
226 | 228 | t.Fatalf("sys4 with conflicting management IP and ipv6.ovn.ranges passed validation")
|
227 | 229 | }
|
228 | 230 | }
|
| 231 | + |
| 232 | +func newNetwork(ifaceName, ipStr string) *Network { |
| 233 | + ip, subnet, _ := net.ParseCIDR(ipStr) |
| 234 | + return &Network{ |
| 235 | + Interface: net.Interface{Name: ifaceName}, |
| 236 | + IP: ip, |
| 237 | + Subnet: subnet, |
| 238 | + } |
| 239 | +} |
| 240 | + |
| 241 | +func TestValidateSystemsNetworkCollision(t *testing.T) { |
| 242 | + tests := []struct { |
| 243 | + name string |
| 244 | + systems map[string]InitSystem |
| 245 | + expectedWarnings []string |
| 246 | + }{ |
| 247 | + { |
| 248 | + name: "no collisions", |
| 249 | + systems: map[string]InitSystem{ |
| 250 | + "system1": { |
| 251 | + MicroCephPublicNetwork: newNetwork("eth0", "10.0.1.0/24"), |
| 252 | + MicroCephInternalNetwork: newNetwork("eth1", "10.0.2.0/24"), |
| 253 | + MicroCloudInternalNetwork: newNetwork("eth2", "10.0.3.0/24"), |
| 254 | + OVNGeneveNetwork: newNetwork("eth3", "10.0.4.0/24"), |
| 255 | + }, |
| 256 | + "system2": { |
| 257 | + MicroCephPublicNetwork: newNetwork("eth0", "10.1.1.0/24"), |
| 258 | + MicroCephInternalNetwork: newNetwork("eth1", "10.1.2.0/24"), |
| 259 | + MicroCloudInternalNetwork: newNetwork("eth2", "10.1.3.0/24"), |
| 260 | + OVNGeneveNetwork: newNetwork("eth3", "10.1.4.0/24"), |
| 261 | + }, |
| 262 | + }, |
| 263 | + expectedWarnings: nil, |
| 264 | + }, |
| 265 | + { |
| 266 | + name: "single system interface collision", |
| 267 | + systems: map[string]InitSystem{ |
| 268 | + "system1": { |
| 269 | + MicroCephInternalNetwork: newNetwork("eth0", "10.0.1.0/24"), |
| 270 | + OVNGeneveNetwork: newNetwork("eth0", "10.0.2.0/24"), // Same interface |
| 271 | + MicroCloudInternalNetwork: newNetwork("eth1", "10.0.3.0/24"), |
| 272 | + }, |
| 273 | + }, |
| 274 | + expectedWarnings: []string{ |
| 275 | + "- Ceph cluster network, OVN underlay sharing network interface \"eth0\"", |
| 276 | + }, |
| 277 | + }, |
| 278 | + { |
| 279 | + name: "cross-system subnet collision", |
| 280 | + systems: map[string]InitSystem{ |
| 281 | + "system1": { |
| 282 | + MicroCephInternalNetwork: newNetwork("eth0", "10.0.1.0/24"), // Same subnet |
| 283 | + OVNGeneveNetwork: newNetwork("eth1", "10.0.2.0/24"), |
| 284 | + MicroCloudInternalNetwork: newNetwork("eth2", "10.0.3.0/24"), |
| 285 | + }, |
| 286 | + "system2": { |
| 287 | + OVNGeneveNetwork: newNetwork("eth3", "10.0.1.0/24"), // Same subnet for different network type |
| 288 | + MicroCloudInternalNetwork: newNetwork("eth4", "10.0.4.0/24"), |
| 289 | + }, |
| 290 | + }, |
| 291 | + expectedWarnings: []string{ |
| 292 | + "- Ceph cluster network, OVN underlay sharing subnet \"10.0.1.0/24\"", |
| 293 | + }, |
| 294 | + }, |
| 295 | + { |
| 296 | + name: "mixed interface and cross-subnet collision", |
| 297 | + systems: map[string]InitSystem{ |
| 298 | + "system1": { |
| 299 | + MicroCephInternalNetwork: newNetwork("eth0", "10.0.1.0/24"), // Interface and subnet collision |
| 300 | + OVNGeneveNetwork: newNetwork("eth0", "10.0.1.0/24"), // Same interface and subnet |
| 301 | + MicroCloudInternalNetwork: newNetwork("eth1", "10.0.2.0/24"), |
| 302 | + }, |
| 303 | + "system2": { |
| 304 | + OVNGeneveNetwork: newNetwork("eth2", "10.0.1.0/24"), // Same subnet globally |
| 305 | + }, |
| 306 | + }, |
| 307 | + expectedWarnings: []string{ |
| 308 | + "- Ceph cluster network, OVN underlay sharing network interface \"eth0\"", |
| 309 | + "- Ceph cluster network, OVN underlay sharing subnet \"10.0.1.0/24\"", |
| 310 | + }, |
| 311 | + }, |
| 312 | + { |
| 313 | + name: "ignore systems with missing networks", |
| 314 | + systems: map[string]InitSystem{ |
| 315 | + "system1": { // Incomplete networks (skipped in checks) |
| 316 | + OVNGeneveNetwork: newNetwork("eth0", "10.0.1.0/24"), |
| 317 | + MicroCloudInternalNetwork: newNetwork("eth1", "10.0.2.0/24"), |
| 318 | + }, |
| 319 | + }, |
| 320 | + expectedWarnings: nil, |
| 321 | + }, |
| 322 | + } |
| 323 | + |
| 324 | + for _, tt := range tests { |
| 325 | + t.Run(tt.name, func(t *testing.T) { |
| 326 | + warnings := detectCollisions(tt.systems) |
| 327 | + assert.ElementsMatch(t, tt.expectedWarnings, warnings) |
| 328 | + }) |
| 329 | + } |
| 330 | +} |
0 commit comments