Esempio n. 1
0
File: types.go Progetto: bac/juju
func interfaceAddressToNetworkConfig(interfaceName, configType string, address net.Addr) (params.NetworkConfig, error) {
	config := params.NetworkConfig{
		ConfigType: configType,
	}

	cidrAddress := address.String()
	if cidrAddress == "" {
		return config, nil
	}

	ip, ipNet, err := net.ParseCIDR(cidrAddress)
	if err != nil {
		logger.Infof("cannot parse %q on interface %q as CIDR, trying as IP address: %v", cidrAddress, interfaceName, err)
		if ip = net.ParseIP(cidrAddress); ip == nil {
			return config, errors.Errorf("cannot parse IP address %q on interface %q", cidrAddress, interfaceName)
		} else {
			ipNet = &net.IPNet{IP: ip}
		}
	}
	if ip.To4() == nil {
		logger.Debugf("skipping observed IPv6 address %q on %q: not fully supported yet", ip, interfaceName)
		// TODO(dimitern): Treat IPv6 addresses as empty until we can handle
		// them reliably.
		return config, nil
	}

	if ipNet.Mask != nil {
		config.CIDR = ipNet.String()
	}
	config.Address = ip.String()
	if configType != string(network.ConfigLoopback) {
		config.ConfigType = string(network.ConfigStatic)
	}

	// TODO(dimitern): Add DNS servers, search domains, and gateway
	// later.

	return config, nil
}
Esempio n. 2
0
File: types.go Progetto: makyo/juju
// MergeProviderAndObservedNetworkConfigs returns the effective, sorted, network
// configs after merging providerConfig with observedConfig.
func MergeProviderAndObservedNetworkConfigs(providerConfigs, observedConfigs []params.NetworkConfig) []params.NetworkConfig {
	providerConfigsByName := make(map[string][]params.NetworkConfig)
	sortedProviderConfigs := SortNetworkConfigsByParents(providerConfigs)
	for _, config := range sortedProviderConfigs {
		name := config.InterfaceName
		providerConfigsByName[name] = append(providerConfigsByName[name], config)
	}

	jsonProviderConfig, err := NetworkConfigsToIndentedJSON(sortedProviderConfigs)
	if err != nil {
		logger.Warningf("cannot serialize provider config %#v as JSON: %v", sortedProviderConfigs, err)
	} else {
		logger.Debugf("provider network config of machine:\n%s", jsonProviderConfig)
	}

	sortedObservedConfigs := SortNetworkConfigsByParents(observedConfigs)

	jsonObservedConfig, err := NetworkConfigsToIndentedJSON(sortedObservedConfigs)
	if err != nil {
		logger.Warningf("cannot serialize observed config %#v as JSON: %v", sortedObservedConfigs, err)
	} else {
		logger.Debugf("observed network config of machine:\n%s", jsonObservedConfig)
	}

	var mergedConfigs []params.NetworkConfig
	for _, config := range sortedObservedConfigs {
		name := config.InterfaceName
		logger.Tracef("merging observed config for device %q: %+v", name, config)
		if strings.HasPrefix(name, instancecfg.DefaultBridgePrefix) {
			logger.Tracef("found potential juju bridge %q in observed config", name)
			unprefixedName := strings.TrimPrefix(name, instancecfg.DefaultBridgePrefix)
			underlyingConfigs, underlyingKnownByProvider := providerConfigsByName[unprefixedName]
			logger.Tracef("device %q underlying %q has provider config: %+v", name, unprefixedName, underlyingConfigs)
			if underlyingKnownByProvider {
				// This config is for a bridge created by Juju and not known by
				// the provider. The bridge is configured to adopt the address
				// allocated to the underlying interface, which is known by the
				// provider. However, since the same underlying interface can
				// have multiple addresses, we need to match the adopted
				// bridgeConfig to the correct address.

				var underlyingConfig params.NetworkConfig
				for i, underlying := range underlyingConfigs {
					if underlying.Address == config.Address {
						logger.Tracef("replacing undelying config %+v", underlying)
						// Remove what we found before changing it below.
						underlyingConfig = underlying
						underlyingConfigs = append(underlyingConfigs[:i], underlyingConfigs[i+1:]...)
						break
					}
				}
				logger.Tracef("underlying provider config after update: %+v", underlyingConfigs)

				bridgeConfig := config
				bridgeConfig.InterfaceType = string(network.BridgeInterface)
				bridgeConfig.ConfigType = underlyingConfig.ConfigType
				bridgeConfig.VLANTag = underlyingConfig.VLANTag
				bridgeConfig.ProviderId = "" // Juju-created bridges never have a ProviderID
				bridgeConfig.ProviderSpaceId = underlyingConfig.ProviderSpaceId
				bridgeConfig.ProviderVLANId = underlyingConfig.ProviderVLANId
				bridgeConfig.ProviderSubnetId = underlyingConfig.ProviderSubnetId
				bridgeConfig.ProviderAddressId = underlyingConfig.ProviderAddressId
				if underlyingParent := underlyingConfig.ParentInterfaceName; underlyingParent != "" {
					bridgeConfig.ParentInterfaceName = instancecfg.DefaultBridgePrefix + underlyingParent
				}

				underlyingConfig.ConfigType = string(network.ConfigManual)
				underlyingConfig.ParentInterfaceName = name
				underlyingConfig.ProviderAddressId = ""
				underlyingConfig.CIDR = ""
				underlyingConfig.Address = ""

				underlyingConfigs = append(underlyingConfigs, underlyingConfig)
				providerConfigsByName[unprefixedName] = underlyingConfigs
				logger.Tracef("updated provider network config by name: %+v", providerConfigsByName)

				mergedConfigs = append(mergedConfigs, bridgeConfig)
				continue
			}
		}

		knownProviderConfigs, knownByProvider := providerConfigsByName[name]
		if !knownByProvider {
			// Not known by the provider and not a Juju-created bridge, so just
			// use the observed config for it.
			logger.Tracef("device %q not known to provider - adding only observed config: %+v", name, config)
			mergedConfigs = append(mergedConfigs, config)
			continue
		}
		logger.Tracef("device %q has known provider network config: %+v", name, knownProviderConfigs)

		for _, providerConfig := range knownProviderConfigs {
			if providerConfig.Address == config.Address {
				logger.Tracef(
					"device %q has observed address %q, index %d, and MTU %q; overriding index %d and MTU %d from provider config",
					name, config.Address, config.DeviceIndex, config.MTU, providerConfig.DeviceIndex, providerConfig.MTU,
				)
				// Prefer observed device indices and MTU values as more up-to-date.
				providerConfig.DeviceIndex = config.DeviceIndex
				providerConfig.MTU = config.MTU

				mergedConfigs = append(mergedConfigs, providerConfig)
				break
			}
		}
	}

	sortedMergedConfigs := SortNetworkConfigsByParents(mergedConfigs)

	jsonMergedConfig, err := NetworkConfigsToIndentedJSON(sortedMergedConfigs)
	if err != nil {
		logger.Warningf("cannot serialize merged config %#v as JSON: %v", sortedMergedConfigs, err)
	} else {
		logger.Debugf("combined machine network config:\n%s", jsonMergedConfig)
	}

	return mergedConfigs
}