forked from cloudfoundry/bosh-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
interface_configuration_creator.go
156 lines (130 loc) · 5.73 KB
/
interface_configuration_creator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package net
import (
boshsettings "github.com/cloudfoundry/bosh-agent/settings"
bosherr "github.com/cloudfoundry/bosh-utils/errors"
boshlog "github.com/cloudfoundry/bosh-utils/logger"
boshsys "github.com/cloudfoundry/bosh-utils/system"
)
type StaticInterfaceConfiguration struct {
Name string
Address string
Netmask string
Network string
Broadcast string
IsDefaultForGateway bool
Mac string
Gateway string
}
type StaticInterfaceConfigurations []StaticInterfaceConfiguration
func (configs StaticInterfaceConfigurations) Len() int {
return len(configs)
}
func (configs StaticInterfaceConfigurations) Less(i, j int) bool {
return configs[i].Name < configs[j].Name
}
func (configs StaticInterfaceConfigurations) Swap(i, j int) {
configs[i], configs[j] = configs[j], configs[i]
}
type DHCPInterfaceConfiguration struct {
Name string
}
type DHCPInterfaceConfigurations []DHCPInterfaceConfiguration
func (configs DHCPInterfaceConfigurations) Len() int {
return len(configs)
}
func (configs DHCPInterfaceConfigurations) Less(i, j int) bool {
return configs[i].Name < configs[j].Name
}
func (configs DHCPInterfaceConfigurations) Swap(i, j int) {
configs[i], configs[j] = configs[j], configs[i]
}
type InterfaceConfigurationCreator interface {
CreateInterfaceConfigurations(boshsettings.Networks, map[string]string) ([]StaticInterfaceConfiguration, []DHCPInterfaceConfiguration, error)
}
type interfaceConfigurationCreator struct {
logger boshlog.Logger
logTag string
}
func NewInterfaceConfigurationCreator(logger boshlog.Logger) InterfaceConfigurationCreator {
return interfaceConfigurationCreator{
logger: logger,
logTag: "interfaceConfigurationCreator",
}
}
func (creator interfaceConfigurationCreator) createInterfaceConfiguration(staticConfigs []StaticInterfaceConfiguration, dhcpConfigs []DHCPInterfaceConfiguration, ifaceName string, networkSettings boshsettings.Network) ([]StaticInterfaceConfiguration, []DHCPInterfaceConfiguration, error) {
creator.logger.Debug(creator.logTag, "Creating network configuration with settings: %s", networkSettings)
if networkSettings.IsDHCP() || networkSettings.Mac == "" {
creator.logger.Debug(creator.logTag, "Using dhcp networking")
dhcpConfigs = append(dhcpConfigs, DHCPInterfaceConfiguration{
Name: ifaceName,
})
} else {
creator.logger.Debug(creator.logTag, "Using static networking")
networkAddress, broadcastAddress, err := boshsys.CalculateNetworkAndBroadcast(networkSettings.IP, networkSettings.Netmask)
if err != nil {
return nil, nil, bosherr.WrapError(err, "Calculating Network and Broadcast")
}
staticConfigs = append(staticConfigs, StaticInterfaceConfiguration{
Name: ifaceName,
Address: networkSettings.IP,
Netmask: networkSettings.Netmask,
Network: networkAddress,
IsDefaultForGateway: networkSettings.IsDefaultFor("gateway"),
Broadcast: broadcastAddress,
Mac: networkSettings.Mac,
Gateway: networkSettings.Gateway,
})
}
return staticConfigs, dhcpConfigs, nil
}
func (creator interfaceConfigurationCreator) CreateInterfaceConfigurations(networks boshsettings.Networks, interfacesByMAC map[string]string) ([]StaticInterfaceConfiguration, []DHCPInterfaceConfiguration, error) {
// In cases where we only have one network and it has no MAC address (either because the IAAS doesn't give us one or
// it's an old CPI), if we only have one interface, we should map them
if len(networks) == 1 && len(interfacesByMAC) == 1 {
networkSettings := creator.getFirstNetwork(networks)
if networkSettings.Mac == "" {
var ifaceName string
networkSettings.Mac, ifaceName = creator.getFirstInterface(interfacesByMAC)
return creator.createInterfaceConfiguration([]StaticInterfaceConfiguration{}, []DHCPInterfaceConfiguration{}, ifaceName, networkSettings)
}
}
return creator.createMultipleInterfaceConfigurations(networks, interfacesByMAC)
}
func (creator interfaceConfigurationCreator) createMultipleInterfaceConfigurations(networks boshsettings.Networks, interfacesByMAC map[string]string) ([]StaticInterfaceConfiguration, []DHCPInterfaceConfiguration, error) {
if len(interfacesByMAC) < len(networks) {
return nil, nil, bosherr.Errorf("Number of network settings '%d' is greater than the number of network devices '%d'", len(networks), len(interfacesByMAC))
}
for name := range networks {
if mac := networks[name].Mac; mac != "" {
if _, ok := interfacesByMAC[mac]; !ok {
return nil, nil, bosherr.Errorf("No device found for network '%s' with MAC address '%s'", name, mac)
}
}
}
// Configure interfaces with network settings matching MAC address.
// If we cannot find a network setting with a matching MAC address, configure that interface as DHCP
var networkSettings boshsettings.Network
var err error
staticConfigs := []StaticInterfaceConfiguration{}
dhcpConfigs := []DHCPInterfaceConfiguration{}
for mac, ifaceName := range interfacesByMAC {
networkSettings, _ = networks.NetworkForMac(mac)
staticConfigs, dhcpConfigs, err = creator.createInterfaceConfiguration(staticConfigs, dhcpConfigs, ifaceName, networkSettings)
if err != nil {
return nil, nil, bosherr.WrapError(err, "Creating interface configuration")
}
}
return staticConfigs, dhcpConfigs, nil
}
func (creator interfaceConfigurationCreator) getFirstNetwork(networks boshsettings.Networks) boshsettings.Network {
for networkName := range networks {
return networks[networkName]
}
return boshsettings.Network{}
}
func (creator interfaceConfigurationCreator) getFirstInterface(interfacesByMAC map[string]string) (string, string) {
for mac := range interfacesByMAC {
return mac, interfacesByMAC[mac]
}
return "", ""
}