2015-01-24 19:32:33 -08:00
|
|
|
// Copyright 2015 CoreOS, Inc.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2014-10-17 15:36:22 -07:00
|
|
|
|
2014-08-15 18:14:34 -07:00
|
|
|
package network
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/coreos/coreos-cloudinit/datasource/metadata/digitalocean"
|
|
|
|
)
|
|
|
|
|
|
|
|
func ProcessDigitalOceanNetconf(config string) ([]InterfaceGenerator, error) {
|
|
|
|
log.Println("Processing DigitalOcean network config")
|
|
|
|
if config == "" {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var cfg digitalocean.Metadata
|
|
|
|
if err := json.Unmarshal([]byte(config), &cfg); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Println("Parsing nameservers")
|
|
|
|
nameservers, err := parseNameservers(cfg.DNS)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
log.Printf("Parsed %d nameservers\n", len(nameservers))
|
|
|
|
|
|
|
|
log.Println("Parsing interfaces")
|
|
|
|
generators, err := parseInterfaces(cfg.Interfaces, nameservers)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
log.Printf("Parsed %d network interfaces\n", len(generators))
|
|
|
|
|
|
|
|
log.Println("Processed DigitalOcean network config")
|
|
|
|
return generators, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseNameservers(cfg digitalocean.DNS) ([]net.IP, error) {
|
|
|
|
nameservers := make([]net.IP, 0, len(cfg.Nameservers))
|
|
|
|
for _, ns := range cfg.Nameservers {
|
|
|
|
if ip := net.ParseIP(ns); ip == nil {
|
|
|
|
return nil, fmt.Errorf("could not parse %q as nameserver IP address", ns)
|
|
|
|
} else {
|
|
|
|
nameservers = append(nameservers, ip)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nameservers, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseInterfaces(cfg digitalocean.Interfaces, nameservers []net.IP) ([]InterfaceGenerator, error) {
|
|
|
|
generators := make([]InterfaceGenerator, 0, len(cfg.Public)+len(cfg.Private))
|
|
|
|
for _, iface := range cfg.Public {
|
|
|
|
if generator, err := parseInterface(iface, nameservers, true); err == nil {
|
|
|
|
generators = append(generators, &physicalInterface{*generator})
|
|
|
|
} else {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, iface := range cfg.Private {
|
|
|
|
if generator, err := parseInterface(iface, []net.IP{}, false); err == nil {
|
|
|
|
generators = append(generators, &physicalInterface{*generator})
|
|
|
|
} else {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return generators, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseInterface(iface digitalocean.Interface, nameservers []net.IP, useRoute bool) (*logicalInterface, error) {
|
|
|
|
routes := make([]route, 0)
|
|
|
|
addresses := make([]net.IPNet, 0)
|
|
|
|
if iface.IPv4 != nil {
|
|
|
|
var ip, mask, gateway net.IP
|
|
|
|
if ip = net.ParseIP(iface.IPv4.IPAddress); ip == nil {
|
|
|
|
return nil, fmt.Errorf("could not parse %q as IPv4 address", iface.IPv4.IPAddress)
|
|
|
|
}
|
|
|
|
if mask = net.ParseIP(iface.IPv4.Netmask); mask == nil {
|
|
|
|
return nil, fmt.Errorf("could not parse %q as IPv4 mask", iface.IPv4.Netmask)
|
|
|
|
}
|
|
|
|
addresses = append(addresses, net.IPNet{
|
|
|
|
IP: ip,
|
|
|
|
Mask: net.IPMask(mask),
|
|
|
|
})
|
|
|
|
|
|
|
|
if useRoute {
|
|
|
|
if gateway = net.ParseIP(iface.IPv4.Gateway); gateway == nil {
|
|
|
|
return nil, fmt.Errorf("could not parse %q as IPv4 gateway", iface.IPv4.Gateway)
|
|
|
|
}
|
|
|
|
routes = append(routes, route{
|
|
|
|
destination: net.IPNet{
|
|
|
|
IP: net.IPv4zero,
|
|
|
|
Mask: net.IPMask(net.IPv4zero),
|
|
|
|
},
|
|
|
|
gateway: gateway,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if iface.IPv6 != nil {
|
|
|
|
var ip, gateway net.IP
|
|
|
|
if ip = net.ParseIP(iface.IPv6.IPAddress); ip == nil {
|
|
|
|
return nil, fmt.Errorf("could not parse %q as IPv6 address", iface.IPv6.IPAddress)
|
|
|
|
}
|
|
|
|
addresses = append(addresses, net.IPNet{
|
|
|
|
IP: ip,
|
|
|
|
Mask: net.CIDRMask(iface.IPv6.Cidr, net.IPv6len*8),
|
|
|
|
})
|
|
|
|
|
|
|
|
if useRoute {
|
|
|
|
if gateway = net.ParseIP(iface.IPv6.Gateway); gateway == nil {
|
|
|
|
return nil, fmt.Errorf("could not parse %q as IPv6 gateway", iface.IPv6.Gateway)
|
|
|
|
}
|
|
|
|
routes = append(routes, route{
|
|
|
|
destination: net.IPNet{
|
|
|
|
IP: net.IPv6zero,
|
|
|
|
Mask: net.IPMask(net.IPv6zero),
|
|
|
|
},
|
|
|
|
gateway: gateway,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hwaddr, err := net.ParseMAC(iface.MAC)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if nameservers == nil {
|
|
|
|
nameservers = []net.IP{}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &logicalInterface{
|
|
|
|
hwaddr: hwaddr,
|
|
|
|
config: configMethodStatic{
|
|
|
|
addresses: addresses,
|
|
|
|
nameservers: nameservers,
|
|
|
|
routes: routes,
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|