1
0
mirror of https://github.com/rancher/os.git synced 2025-06-27 23:36:49 +00:00

Refactor the cloud-init metadata to return a netconf.NetworkConfig

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
This commit is contained in:
Sven Dowideit 2017-03-07 13:21:14 +10:00
parent 5dbb0f2a28
commit 0779e13d46
23 changed files with 459 additions and 287 deletions

View File

@ -16,8 +16,10 @@
package cloudinitsave package cloudinitsave
import ( import (
"bytes"
"errors" "errors"
"os" "os"
"path"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -110,8 +112,8 @@ func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadat
if err := util.WriteFileAtomic(rancherConfig.CloudConfigBootFile, cloudConfigBytes, 400); err != nil { if err := util.WriteFileAtomic(rancherConfig.CloudConfigBootFile, cloudConfigBytes, 400); err != nil {
return err return err
} }
// Don't put secrets into the log // TODO: Don't put secrets into the log
//log.Infof("Written to %s:\n%s", rancherConfig.CloudConfigBootFile, string(cloudConfigBytes)) log.Infof("Written to %s:\n%s", rancherConfig.CloudConfigBootFile, string(cloudConfigBytes))
} }
metaDataBytes, err := yaml.Marshal(metadata) metaDataBytes, err := yaml.Marshal(metadata)
@ -122,8 +124,34 @@ func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadat
if err = util.WriteFileAtomic(rancherConfig.MetaDataFile, metaDataBytes, 400); err != nil { if err = util.WriteFileAtomic(rancherConfig.MetaDataFile, metaDataBytes, 400); err != nil {
return err return err
} }
// Don't put secrets into the log // TODO: Don't put secrets into the log
//log.Infof("Written to %s:\n%s", rancherConfig.MetaDataFile, string(metaDataBytes)) log.Infof("Written to %s:\n%s", rancherConfig.MetaDataFile, string(metaDataBytes))
// if we write the empty meta yml, the merge fails.
// TODO: the problem is that a partially filled one will still have merge issues, so that needs fixing - presumably by making merge more clever, and making more fields optional
emptyMeta, err := yaml.Marshal(datasource.Metadata{})
if err != nil {
return err
}
if bytes.Compare(metaDataBytes, emptyMeta) == 0 {
log.Infof("not writing %s: its all defaults.", rancherConfig.CloudConfigNetworkFile)
return nil
}
// write the network.yml file from metadata
cc := rancherConfig.CloudConfig{
Rancher: rancherConfig.RancherConfig{
Network: metadata.NetworkConfig,
},
}
if err := os.MkdirAll(path.Dir(rancherConfig.CloudConfigNetworkFile), 0700); err != nil {
log.Errorf("Failed to create directory for file %s: %v", rancherConfig.CloudConfigNetworkFile, err)
}
if err := rancherConfig.WriteToFile(cc, rancherConfig.CloudConfigNetworkFile); err != nil {
log.Errorf("Failed to save config file %s: %v", rancherConfig.CloudConfigNetworkFile, err)
}
log.Infof("Written to %s:", rancherConfig.CloudConfigNetworkFile)
return nil return nil
} }
@ -161,7 +189,7 @@ func fetchAndSave(ds datasource.Datasource) error {
userDataBytes = []byte{} userDataBytes = []byte{}
} }
} else { } else {
log.Errorf("Unrecognized user-data\n%s", userData) log.Errorf("Unrecognized user-data\n(%s)", userData)
userDataBytes = []byte{} userDataBytes = []byte{}
} }
@ -233,8 +261,8 @@ func getDatasources(cfg *rancherConfig.CloudConfig, network bool) []datasource.D
} }
func enableDoLinkLocal() { func enableDoLinkLocal() {
err := netconf.ApplyNetworkConfigs(&rancherConfig.NetworkConfig{ err := netconf.ApplyNetworkConfigs(&netconf.NetworkConfig{
Interfaces: map[string]rancherConfig.InterfaceConfig{ Interfaces: map[string]netconf.InterfaceConfig{
"eth0": { "eth0": {
IPV4LL: true, IPV4LL: true,
}, },

88
cmd/cloudinitsave/packet.go Normal file → Executable file
View File

@ -1,18 +1,8 @@
package cloudinitsave package cloudinitsave
import ( import (
"bytes"
"fmt"
"net/http"
"os"
"path"
"strings"
"github.com/rancher/os/log" "github.com/rancher/os/log"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/packethost/packngo/metadata"
"github.com/rancher/os/config" "github.com/rancher/os/config"
"github.com/rancher/os/netconf" "github.com/rancher/os/netconf"
) )
@ -34,71 +24,29 @@ func enablePacketNetwork(cfg *config.RancherConfig) {
return return
} }
c := metadata.NewClient(http.DefaultClient) // Post to phone home URL on first boot
m, err := c.Metadata.Get() /*
if err != nil { // TODO: bring this back
log.Errorf("Failed to get Packet metadata: %v", err) if _, err = os.Stat(config.CloudConfigNetworkFile); err != nil {
return if _, err = http.Post(m.PhoneHomeURL, "application/json", bytes.NewReader([]byte{})); err != nil {
} log.Errorf("Failed to post to Packet phone home URL: %v", err)
bondCfg := config.InterfaceConfig{
Addresses: []string{},
BondOpts: map[string]string{
"lacp_rate": "1",
"xmit_hash_policy": "layer3+4",
"downdelay": "200",
"updelay": "200",
"miimon": "100",
"mode": "4",
},
}
netCfg := config.NetworkConfig{
Interfaces: map[string]config.InterfaceConfig{},
}
for _, iface := range m.Network.Interfaces {
netCfg.Interfaces["mac="+iface.Mac] = config.InterfaceConfig{
Bond: "bond0",
}
}
for _, addr := range m.Network.Addresses {
bondCfg.Addresses = append(bondCfg.Addresses, fmt.Sprintf("%s/%d", addr.Address, addr.Cidr))
if addr.Gateway != "" {
if addr.AddressFamily == 4 {
if addr.Public {
bondCfg.Gateway = addr.Gateway
}
} else {
bondCfg.GatewayIpv6 = addr.Gateway
} }
} }
*/
if addr.AddressFamily == 4 && strings.HasPrefix(addr.Gateway, "10.") { /*
bondCfg.PostUp = append(bondCfg.PostUp, "ip route add 10.0.0.0/8 via "+addr.Gateway) cc := config.CloudConfig{
Rancher: config.RancherConfig{
Network: netCfg,
},
} }
}
netCfg.Interfaces["bond0"] = bondCfg if err := os.MkdirAll(path.Dir(config.CloudConfigNetworkFile), 0700); err != nil {
b, _ := yaml.Marshal(netCfg) log.Errorf("Failed to create directory for file %s: %v", config.CloudConfigNetworkFile, err)
log.Debugf("Generated network config: %s", string(b))
cc := config.CloudConfig{
Rancher: config.RancherConfig{
Network: netCfg,
},
}
// Post to phone home URL on first boot
if _, err = os.Stat(config.CloudConfigNetworkFile); err != nil {
if _, err = http.Post(m.PhoneHomeURL, "application/json", bytes.NewReader([]byte{})); err != nil {
log.Errorf("Failed to post to Packet phone home URL: %v", err)
} }
}
if err := os.MkdirAll(path.Dir(config.CloudConfigNetworkFile), 0700); err != nil { if err := config.WriteToFile(cc, config.CloudConfigNetworkFile); err != nil {
log.Errorf("Failed to create directory for file %s: %v", config.CloudConfigNetworkFile, err) log.Errorf("Failed to save config file %s: %v", config.CloudConfigNetworkFile, err)
} }
*/
if err := config.WriteToFile(cc, config.CloudConfigNetworkFile); err != nil {
log.Errorf("Failed to save config file %s: %v", config.CloudConfigNetworkFile, err)
}
} }

View File

@ -28,6 +28,7 @@ func ApplyNetworkConfig(cfg *config.CloudConfig) {
search = cfg.Rancher.Defaults.Network.DNS.Search search = cfg.Rancher.Defaults.Network.DNS.Search
} }
// TODO: don't write to the file if nameservers is still empty
if _, err := resolvconf.Build("/etc/resolv.conf", nameservers, search, nil); err != nil { if _, err := resolvconf.Build("/etc/resolv.conf", nameservers, search, nil); err != nil {
log.Error(err) log.Error(err)
} }

View File

@ -102,10 +102,11 @@ func (cd *ConfigDrive) FetchMetadata() (metadata datasource.Metadata, err error)
metadata.SSHPublicKeys = m.SSHAuthorizedKeyMap metadata.SSHPublicKeys = m.SSHAuthorizedKeyMap
metadata.Hostname = m.Hostname metadata.Hostname = m.Hostname
if m.NetworkConfig.ContentPath != "" { // TODO: I don't think we've used this for anything
metadata.NetworkConfig, err = cd.tryReadFile(path.Join(cd.openstackRoot(), m.NetworkConfig.ContentPath)) /* if m.NetworkConfig.ContentPath != "" {
} metadata.NetworkConfig, err = cd.tryReadFile(path.Join(cd.openstackRoot(), m.NetworkConfig.ContentPath))
}
*/
return return
} }

View File

@ -48,8 +48,7 @@ func TestFetchMetadata(t *testing.T) {
test.File{Path: "/media/configdrive/openstack/config_file.json", Contents: "make it work"}, test.File{Path: "/media/configdrive/openstack/config_file.json", Contents: "make it work"},
), ),
metadata: datasource.Metadata{ metadata: datasource.Metadata{
Hostname: "host", Hostname: "host",
NetworkConfig: []byte("make it work"),
SSHPublicKeys: map[string]string{ SSHPublicKeys: map[string]string{
"1": "key1", "1": "key1",
"2": "key2", "2": "key2",

View File

@ -16,6 +16,8 @@ package datasource
import ( import (
"net" "net"
"github.com/rancher/os/netconf"
) )
type Datasource interface { type Datasource interface {
@ -31,11 +33,17 @@ type Datasource interface {
} }
type Metadata struct { type Metadata struct {
PublicIPv4 net.IP // TODO: move to netconf/types.go ?
PublicIPv6 net.IP // see https://ahmetalpbalkan.com/blog/comparison-of-instance-metadata-services/
PrivateIPv4 net.IP
PrivateIPv6 net.IP
Hostname string Hostname string
SSHPublicKeys map[string]string SSHPublicKeys map[string]string
NetworkConfig interface{} NetworkConfig netconf.NetworkConfig
// probably unused, but its in the initialize.env code
// TODO: work out if there's any reason to keep it.
// Lets see if anyone notices when its not set.
PublicIPv4 net.IP
PublicIPv6 net.IP
PrivateIPv4 net.IP
PrivateIPv6 net.IP
} }

View File

@ -16,9 +16,13 @@ package digitalocean
import ( import (
"encoding/json" "encoding/json"
"net" "fmt"
"strconv" "strconv"
"github.com/rancher/os/netconf"
"net"
"github.com/rancher/os/config/cloudinit/datasource" "github.com/rancher/os/config/cloudinit/datasource"
"github.com/rancher/os/config/cloudinit/datasource/metadata" "github.com/rancher/os/config/cloudinit/datasource/metadata"
) )
@ -99,12 +103,70 @@ func (ms *MetadataService) FetchMetadata() (metadata datasource.Metadata, err er
metadata.PrivateIPv6 = net.ParseIP(m.Interfaces.Private[0].IPv6.IPAddress) metadata.PrivateIPv6 = net.ParseIP(m.Interfaces.Private[0].IPv6.IPAddress)
} }
} }
metadata.NetworkConfig.Interfaces = make(map[string]netconf.InterfaceConfig)
ethNumber := 0
for _, eth := range m.Interfaces.Public {
network := netconf.InterfaceConfig{}
if eth.IPv4 != nil {
network.Gateway = eth.IPv4.Gateway
network.Addresses = append(network.Addresses, fmt.Sprintf("%s/%s", eth.IPv4.IPAddress, eth.IPv4.Netmask))
if metadata.PublicIPv4 == nil {
metadata.PublicIPv4 = net.ParseIP(eth.IPv4.IPAddress)
}
}
if eth.AnchorIPv4 != nil {
network.Addresses = append(network.Addresses, fmt.Sprintf("%s/%s", eth.AnchorIPv4.IPAddress, eth.AnchorIPv4.Netmask))
}
if eth.IPv6 != nil {
network.Addresses = append(network.Addresses, eth.IPv6.IPAddress)
network.GatewayIpv6 = eth.IPv6.Gateway
if metadata.PublicIPv6 == nil {
metadata.PublicIPv6 = net.ParseIP(eth.IPv6.IPAddress)
}
}
metadata.NetworkConfig.Interfaces[fmt.Sprintf("eth%d", ethNumber)] = network
ethNumber = ethNumber + 1
}
for _, eth := range m.Interfaces.Private {
network := netconf.InterfaceConfig{}
if eth.IPv4 != nil {
network.Gateway = eth.IPv4.Gateway
network.Addresses = append(network.Addresses, fmt.Sprintf("%s/%s", eth.IPv4.IPAddress, eth.IPv4.Netmask))
if metadata.PrivateIPv4 == nil {
metadata.PrivateIPv4 = net.ParseIP(eth.IPv6.IPAddress)
}
}
if eth.AnchorIPv4 != nil {
network.Addresses = append(network.Addresses, fmt.Sprintf("%s/%s", eth.AnchorIPv4.IPAddress, eth.AnchorIPv4.Netmask))
}
if eth.IPv6 != nil {
network.Address = eth.IPv6.IPAddress
network.GatewayIpv6 = eth.IPv6.Gateway
if metadata.PrivateIPv6 == nil {
metadata.PrivateIPv6 = net.ParseIP(eth.IPv6.IPAddress)
}
}
metadata.NetworkConfig.Interfaces[fmt.Sprintf("eth%d", ethNumber)] = network
ethNumber = ethNumber + 1
}
metadata.NetworkConfig.DNS.Nameservers = m.DNS.Nameservers
metadata.Hostname = m.Hostname metadata.Hostname = m.Hostname
metadata.SSHPublicKeys = map[string]string{} metadata.SSHPublicKeys = map[string]string{}
for i, key := range m.PublicKeys { for i, key := range m.PublicKeys {
metadata.SSHPublicKeys[strconv.Itoa(i)] = key metadata.SSHPublicKeys[strconv.Itoa(i)] = key
} }
metadata.NetworkConfig = m // metadata.NetworkConfig = m
return return
} }

View File

@ -20,6 +20,8 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/rancher/os/netconf"
"github.com/rancher/os/config/cloudinit/datasource" "github.com/rancher/os/config/cloudinit/datasource"
"github.com/rancher/os/config/cloudinit/datasource/metadata" "github.com/rancher/os/config/cloudinit/datasource/metadata"
"github.com/rancher/os/config/cloudinit/datasource/metadata/test" "github.com/rancher/os/config/cloudinit/datasource/metadata/test"
@ -90,26 +92,23 @@ func TestFetchMetadata(t *testing.T) {
"0": "publickey1", "0": "publickey1",
"1": "publickey2", "1": "publickey2",
}, },
NetworkConfig: Metadata{ NetworkConfig: netconf.NetworkConfig{
Interfaces: Interfaces{ Interfaces: map[string]netconf.InterfaceConfig{
Public: []Interface{ "eth0": netconf.InterfaceConfig{
{ Addresses: []string{
IPv4: &Address{ "192.168.1.2/255.255.255.0",
IPAddress: "192.168.1.2", "fe00::",
Netmask: "255.255.255.0",
Gateway: "192.168.1.1",
},
IPv6: &Address{
IPAddress: "fe00::",
Cidr: 126,
Gateway: "fe00::",
},
MAC: "ab:cd:ef:gh:ij",
Type: "public",
}, },
//Netmask: "255.255.255.0",
Gateway: "192.168.1.1",
//Cidr: 126,
GatewayIpv6: "fe00::",
//MAC: "ab:cd:ef:gh:ij",
//Type: "public",
}, },
}, },
PublicKeys: []string{"publickey1", "publickey2"}, //PublicKeys: []string{"publickey1", "publickey2"},
}, },
}, },
}, },
@ -127,10 +126,10 @@ func TestFetchMetadata(t *testing.T) {
} }
metadata, err := service.FetchMetadata() metadata, err := service.FetchMetadata()
if Error(err) != Error(tt.expectErr) { if Error(err) != Error(tt.expectErr) {
t.Fatalf("bad error (%q): want %q, got %q", tt.resources, tt.expectErr, err) t.Fatalf("bad error (%q): \nwant %#v,\n got %#v", tt.resources, tt.expectErr, err)
} }
if !reflect.DeepEqual(tt.expect, metadata) { if !reflect.DeepEqual(tt.expect, metadata) {
t.Fatalf("bad fetch (%q): want %#q, got %#q", tt.resources, tt.expect, metadata) t.Fatalf("bad fetch (%q): \nwant %#v,\n got %#v", tt.resources, tt.expect, metadata)
} }
} }
} }

View File

@ -22,6 +22,8 @@ import (
"net" "net"
"strings" "strings"
"github.com/rancher/os/netconf"
"github.com/rancher/os/config/cloudinit/datasource" "github.com/rancher/os/config/cloudinit/datasource"
"github.com/rancher/os/config/cloudinit/datasource/metadata" "github.com/rancher/os/config/cloudinit/datasource/metadata"
"github.com/rancher/os/config/cloudinit/pkg" "github.com/rancher/os/config/cloudinit/pkg"
@ -47,6 +49,7 @@ func NewDatasource(root string) *MetadataService {
func (ms MetadataService) FetchMetadata() (datasource.Metadata, error) { func (ms MetadataService) FetchMetadata() (datasource.Metadata, error) {
metadata := datasource.Metadata{} metadata := datasource.Metadata{}
metadata.NetworkConfig = netconf.NetworkConfig{}
if keynames, err := ms.fetchAttributes(fmt.Sprintf("%s/public-keys", ms.MetadataURL())); err == nil { if keynames, err := ms.fetchAttributes(fmt.Sprintf("%s/public-keys", ms.MetadataURL())); err == nil {
keyIDs := make(map[string]string) keyIDs := make(map[string]string)
@ -77,18 +80,25 @@ func (ms MetadataService) FetchMetadata() (datasource.Metadata, error) {
return metadata, err return metadata, err
} }
network := netconf.InterfaceConfig{}
if localAddr, err := ms.fetchAttribute(fmt.Sprintf("%s/local-ipv4", ms.MetadataURL())); err == nil { if localAddr, err := ms.fetchAttribute(fmt.Sprintf("%s/local-ipv4", ms.MetadataURL())); err == nil {
metadata.PrivateIPv4 = net.ParseIP(localAddr) metadata.PrivateIPv4 = net.ParseIP(localAddr)
network.Addresses = append(network.Addresses, localAddr)
} else if _, ok := err.(pkg.ErrNotFound); !ok { } else if _, ok := err.(pkg.ErrNotFound); !ok {
return metadata, err return metadata, err
} }
if publicAddr, err := ms.fetchAttribute(fmt.Sprintf("%s/public-ipv4", ms.MetadataURL())); err == nil { if publicAddr, err := ms.fetchAttribute(fmt.Sprintf("%s/public-ipv4", ms.MetadataURL())); err == nil {
metadata.PublicIPv4 = net.ParseIP(publicAddr) metadata.PublicIPv4 = net.ParseIP(publicAddr)
network.Addresses = append(network.Addresses, publicAddr)
} else if _, ok := err.(pkg.ErrNotFound); !ok { } else if _, ok := err.(pkg.ErrNotFound); !ok {
return metadata, err return metadata, err
} }
metadata.NetworkConfig.Interfaces = make(map[string]netconf.InterfaceConfig)
metadata.NetworkConfig.Interfaces["eth0"] = network
return metadata, nil return metadata, nil
} }

View File

@ -24,6 +24,7 @@ import (
"github.com/rancher/os/config/cloudinit/datasource/metadata" "github.com/rancher/os/config/cloudinit/datasource/metadata"
"github.com/rancher/os/config/cloudinit/datasource/metadata/test" "github.com/rancher/os/config/cloudinit/datasource/metadata/test"
"github.com/rancher/os/config/cloudinit/pkg" "github.com/rancher/os/config/cloudinit/pkg"
"github.com/rancher/os/netconf"
) )
func TestType(t *testing.T) { func TestType(t *testing.T) {
@ -174,6 +175,16 @@ func TestFetchMetadata(t *testing.T) {
PrivateIPv4: net.ParseIP("1.2.3.4"), PrivateIPv4: net.ParseIP("1.2.3.4"),
PublicIPv4: net.ParseIP("5.6.7.8"), PublicIPv4: net.ParseIP("5.6.7.8"),
SSHPublicKeys: map[string]string{"test1": "key"}, SSHPublicKeys: map[string]string{"test1": "key"},
NetworkConfig: netconf.NetworkConfig{
Interfaces: map[string]netconf.InterfaceConfig{
"eth0": netconf.InterfaceConfig{
Addresses: []string{
"1.2.3.4",
"5.6.7.8",
},
},
},
},
}, },
}, },
{ {
@ -192,6 +203,16 @@ func TestFetchMetadata(t *testing.T) {
PrivateIPv4: net.ParseIP("1.2.3.4"), PrivateIPv4: net.ParseIP("1.2.3.4"),
PublicIPv4: net.ParseIP("5.6.7.8"), PublicIPv4: net.ParseIP("5.6.7.8"),
SSHPublicKeys: map[string]string{"test1": "key"}, SSHPublicKeys: map[string]string{"test1": "key"},
NetworkConfig: netconf.NetworkConfig{
Interfaces: map[string]netconf.InterfaceConfig{
"eth0": netconf.InterfaceConfig{
Addresses: []string{
"1.2.3.4",
"5.6.7.8",
},
},
},
},
}, },
}, },
{ {

View File

@ -21,6 +21,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/rancher/os/netconf"
"github.com/rancher/os/config/cloudinit/datasource" "github.com/rancher/os/config/cloudinit/datasource"
"github.com/rancher/os/config/cloudinit/datasource/metadata" "github.com/rancher/os/config/cloudinit/datasource/metadata"
) )
@ -72,6 +74,22 @@ func (ms MetadataService) FetchMetadata() (datasource.Metadata, error) {
SSHPublicKeys: nil, SSHPublicKeys: nil,
} }
addresses := []string{}
if public != nil {
addresses = append(addresses, public.String())
}
if local != nil {
addresses = append(addresses, local.String())
}
if len(addresses) > 0 {
network := netconf.InterfaceConfig{
Addresses: addresses,
}
md.NetworkConfig.Interfaces = make(map[string]netconf.InterfaceConfig)
md.NetworkConfig.Interfaces["eth0"] = network
}
keyStrings := strings.Split(projectSSHKeys+"\n"+instanceSSHKeys, "\n") keyStrings := strings.Split(projectSSHKeys+"\n"+instanceSSHKeys, "\n")
i := 0 i := 0

View File

@ -20,6 +20,8 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/rancher/os/netconf"
"github.com/rancher/os/config/cloudinit/datasource" "github.com/rancher/os/config/cloudinit/datasource"
"github.com/rancher/os/config/cloudinit/datasource/metadata" "github.com/rancher/os/config/cloudinit/datasource/metadata"
"github.com/rancher/os/config/cloudinit/datasource/metadata/test" "github.com/rancher/os/config/cloudinit/datasource/metadata/test"
@ -73,6 +75,16 @@ func TestFetchMetadata(t *testing.T) {
Hostname: "host", Hostname: "host",
PrivateIPv4: net.ParseIP("1.2.3.4"), PrivateIPv4: net.ParseIP("1.2.3.4"),
PublicIPv4: net.ParseIP("5.6.7.8"), PublicIPv4: net.ParseIP("5.6.7.8"),
NetworkConfig: netconf.NetworkConfig{
Interfaces: map[string]netconf.InterfaceConfig{
"eth0": netconf.InterfaceConfig{
Addresses: []string{
"5.6.7.8",
"1.2.3.4",
},
},
},
},
}, },
}, },
{ {

View File

@ -20,6 +20,7 @@ import (
"strings" "strings"
"github.com/rancher/os/config/cloudinit/pkg" "github.com/rancher/os/config/cloudinit/pkg"
"github.com/rancher/os/log"
) )
type Service struct { type Service struct {
@ -40,6 +41,9 @@ func NewDatasource(root, apiVersion, userdataPath, metadataPath string, header h
func (ms Service) IsAvailable() bool { func (ms Service) IsAvailable() bool {
_, ms.lastError = ms.Client.Get(ms.Root + ms.APIVersion) _, ms.lastError = ms.Client.Get(ms.Root + ms.APIVersion)
if ms.lastError != nil {
log.Errorf("%s: %s (lastError: %s)", "IsAvailable", ms.Root+":"+ms.UserdataPath, ms.lastError)
}
return (ms.lastError == nil) return (ms.lastError == nil)
} }
@ -48,7 +52,7 @@ func (ms *Service) Finish() error {
} }
func (ms *Service) String() string { func (ms *Service) String() string {
return fmt.Sprintf("%s: %s (lastError: %s)", "metadata", ms.Root+":"+ms.UserdataPath, ms.lastError) return fmt.Sprintf("%s: %s (lastError: %s)", "metadata", ms.Root+ms.UserdataPath, ms.lastError)
} }
func (ms Service) AvailabilityChanges() bool { func (ms Service) AvailabilityChanges() bool {

View File

@ -15,12 +15,18 @@
package packet package packet
import ( import (
"encoding/json" "fmt"
"net" "net/http"
"strconv" "strconv"
"strings"
"github.com/rancher/os/config/cloudinit/datasource" "github.com/rancher/os/config/cloudinit/datasource"
"github.com/rancher/os/config/cloudinit/datasource/metadata" "github.com/rancher/os/config/cloudinit/datasource/metadata"
"github.com/rancher/os/log"
"github.com/rancher/os/netconf"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
packetMetadata "github.com/packethost/packngo/metadata"
) )
const ( const (
@ -30,33 +36,6 @@ const (
metadataPath = "metadata" metadataPath = "metadata"
) )
type Netblock struct {
Address net.IP `json:"address"`
Cidr int `json:"cidr"`
Netmask net.IP `json:"netmask"`
Gateway net.IP `json:"gateway"`
AddressFamily int `json:"address_family"`
Public bool `json:"public"`
}
type Nic struct {
Name string `json:"name"`
Mac string `json:"mac"`
}
type NetworkData struct {
Interfaces []Nic `json:"interfaces"`
Netblocks []Netblock `json:"addresses"`
DNS []net.IP `json:"dns"`
}
// Metadata that will be pulled from the https://metadata.packet.net/metadata only. We have the opportunity to add more later.
type Metadata struct {
Hostname string `json:"hostname"`
SSHKeys []string `json:"ssh_keys"`
NetworkData NetworkData `json:"network"`
}
type MetadataService struct { type MetadataService struct {
metadata.Service metadata.Service
} }
@ -70,37 +49,85 @@ func NewDatasource(root string) *MetadataService {
} }
func (ms *MetadataService) FetchMetadata() (metadata datasource.Metadata, err error) { func (ms *MetadataService) FetchMetadata() (metadata datasource.Metadata, err error) {
var data []byte c := packetMetadata.NewClient(http.DefaultClient)
var m Metadata m, err := c.Metadata.Get()
if err != nil {
if data, err = ms.FetchData(ms.MetadataURL()); err != nil || len(data) == 0 { log.Errorf("Failed to get Packet metadata: %v", err)
return return
} }
if err = json.Unmarshal(data, &m); err != nil { bondCfg := netconf.InterfaceConfig{
return Addresses: []string{},
BondOpts: map[string]string{
"lacp_rate": "1",
"xmit_hash_policy": "layer3+4",
"downdelay": "200",
"updelay": "200",
"miimon": "100",
"mode": "4",
},
} }
netCfg := netconf.NetworkConfig{
if len(m.NetworkData.Netblocks) > 0 { Interfaces: map[string]netconf.InterfaceConfig{},
for _, Netblock := range m.NetworkData.Netblocks { }
if Netblock.AddressFamily == 4 { for _, iface := range m.Network.Interfaces {
if Netblock.Public == true { netCfg.Interfaces["mac="+iface.Mac] = netconf.InterfaceConfig{
metadata.PublicIPv4 = Netblock.Address Bond: "bond0",
} else {
metadata.PrivateIPv4 = Netblock.Address
}
} else {
metadata.PublicIPv6 = Netblock.Address
}
} }
} }
for _, addr := range m.Network.Addresses {
bondCfg.Addresses = append(bondCfg.Addresses, fmt.Sprintf("%s/%d", addr.Address, addr.Cidr))
if addr.Gateway != "" {
if addr.AddressFamily == 4 {
if addr.Public {
bondCfg.Gateway = addr.Gateway
}
} else {
bondCfg.GatewayIpv6 = addr.Gateway
}
}
if addr.AddressFamily == 4 && strings.HasPrefix(addr.Gateway, "10.") {
bondCfg.PostUp = append(bondCfg.PostUp, "ip route add 10.0.0.0/8 via "+addr.Gateway)
}
}
netCfg.Interfaces["bond0"] = bondCfg
b, _ := yaml.Marshal(netCfg)
log.Debugf("Generated network config: %s", string(b))
// the old code var data []byte
/* var m Metadata
if data, err = ms.FetchData(ms.MetadataURL()); err != nil || len(data) == 0 {
return
}
if err = json.Unmarshal(data, &m); err != nil {
return
}
if len(m.NetworkData.Netblocks) > 0 {
for _, Netblock := range m.NetworkData.Netblocks {
if Netblock.AddressFamily == 4 {
if Netblock.Public == true {
metadata.PublicIPv4 = Netblock.Address
} else {
metadata.PrivateIPv4 = Netblock.Address
}
} else {
metadata.PublicIPv6 = Netblock.Address
}
}
}
*/
metadata.Hostname = m.Hostname metadata.Hostname = m.Hostname
metadata.SSHPublicKeys = map[string]string{} metadata.SSHPublicKeys = map[string]string{}
for i, key := range m.SSHKeys { for i, key := range m.SshKeys {
metadata.SSHPublicKeys[strconv.Itoa(i)] = key metadata.SSHPublicKeys[strconv.Itoa(i)] = key
} }
metadata.NetworkConfig = m.NetworkData metadata.NetworkConfig = netCfg
return return
} }

View File

@ -125,7 +125,7 @@ func (v VMWare) FetchMetadata() (metadata datasource.Metadata, err error) {
} }
} }
} }
metadata.NetworkConfig = netconf // metadata.NetworkConfig = netconf
return return
} }

View File

@ -56,10 +56,10 @@ func TestFetchMetadata(t *testing.T) {
"interface.0.dhcp": "yes", "interface.0.dhcp": "yes",
}, },
metadata: datasource.Metadata{ metadata: datasource.Metadata{
NetworkConfig: map[string]string{ // NetworkConfig: map[string]string{
"interface.0.mac": "test mac", // "interface.0.mac": "test mac",
"interface.0.dhcp": "yes", // "interface.0.dhcp": "yes",
}, // },
}, },
}, },
{ {
@ -68,10 +68,10 @@ func TestFetchMetadata(t *testing.T) {
"interface.0.dhcp": "yes", "interface.0.dhcp": "yes",
}, },
metadata: datasource.Metadata{ metadata: datasource.Metadata{
NetworkConfig: map[string]string{ // NetworkConfig: map[string]string{
"interface.0.name": "test name", // "interface.0.name": "test name",
"interface.0.dhcp": "yes", // "interface.0.dhcp": "yes",
}, // },
}, },
}, },
{ {
@ -86,12 +86,12 @@ func TestFetchMetadata(t *testing.T) {
metadata: datasource.Metadata{ metadata: datasource.Metadata{
Hostname: "test host", Hostname: "test host",
PrivateIPv6: net.ParseIP("fe00::100"), PrivateIPv6: net.ParseIP("fe00::100"),
NetworkConfig: map[string]string{ // NetworkConfig: map[string]string{
"interface.0.mac": "test mac", // "interface.0.mac": "test mac",
"interface.0.ip.0.address": "fe00::100/64", // "interface.0.ip.0.address": "fe00::100/64",
"interface.0.route.0.gateway": "fe00::1", // "interface.0.route.0.gateway": "fe00::1",
"interface.0.route.0.destination": "::", // "interface.0.route.0.destination": "::",
}, // },
}, },
}, },
{ {
@ -113,17 +113,17 @@ func TestFetchMetadata(t *testing.T) {
Hostname: "test host", Hostname: "test host",
PublicIPv4: net.ParseIP("10.0.0.101"), PublicIPv4: net.ParseIP("10.0.0.101"),
PrivateIPv4: net.ParseIP("10.0.0.102"), PrivateIPv4: net.ParseIP("10.0.0.102"),
NetworkConfig: map[string]string{ // NetworkConfig: map[string]string{
"interface.0.name": "test name", // "interface.0.name": "test name",
"interface.0.ip.0.address": "10.0.0.100/24", // "interface.0.ip.0.address": "10.0.0.100/24",
"interface.0.ip.1.address": "10.0.0.101/24", // "interface.0.ip.1.address": "10.0.0.101/24",
"interface.0.route.0.gateway": "10.0.0.1", // "interface.0.route.0.gateway": "10.0.0.1",
"interface.0.route.0.destination": "0.0.0.0", // "interface.0.route.0.destination": "0.0.0.0",
"interface.1.mac": "test mac", // "interface.1.mac": "test mac",
"interface.1.route.0.gateway": "10.0.0.2", // "interface.1.route.0.gateway": "10.0.0.2",
"interface.1.route.0.destination": "0.0.0.0", // "interface.1.route.0.destination": "0.0.0.0",
"interface.1.ip.0.address": "10.0.0.102/24", // "interface.1.ip.0.address": "10.0.0.102/24",
}, // },
}, },
}, },
} }
@ -257,17 +257,17 @@ func TestOvfTransport(t *testing.T) {
Hostname: "test host", Hostname: "test host",
PublicIPv4: net.ParseIP("10.0.0.101"), PublicIPv4: net.ParseIP("10.0.0.101"),
PrivateIPv4: net.ParseIP("10.0.0.102"), PrivateIPv4: net.ParseIP("10.0.0.102"),
NetworkConfig: map[string]string{ //NetworkConfig: map[string]string{
"interface.0.name": "test name", // "interface.0.name": "test name",
"interface.0.ip.0.address": "10.0.0.100/24", // "interface.0.ip.0.address": "10.0.0.100/24",
"interface.0.ip.1.address": "10.0.0.101/24", // "interface.0.ip.1.address": "10.0.0.101/24",
"interface.0.route.0.gateway": "10.0.0.1", // "interface.0.route.0.gateway": "10.0.0.1",
"interface.0.route.0.destination": "0.0.0.0", // "interface.0.route.0.destination": "0.0.0.0",
"interface.1.mac": "test mac", // "interface.1.mac": "test mac",
"interface.1.route.0.gateway": "10.0.0.2", // "interface.1.route.0.gateway": "10.0.0.2",
"interface.1.route.0.destination": "0.0.0.0", // "interface.1.route.0.destination": "0.0.0.0",
"interface.1.ip.0.address": "10.0.0.102/24", // "interface.1.ip.0.address": "10.0.0.102/24",
}, // },
}, },
userdata: []byte("test config"), userdata: []byte("test config"),
}, },

72
config/cloudinit/network/packet.go Normal file → Executable file
View File

@ -17,14 +17,15 @@ package network
import ( import (
"net" "net"
"github.com/rancher/os/config/cloudinit/datasource/metadata/packet" "github.com/rancher/os/netconf"
) )
func ProcessPacketNetconf(netdata packet.NetworkData) ([]InterfaceGenerator, error) { func ProcessPacketNetconf(netdata netconf.NetworkConfig) ([]InterfaceGenerator, error) {
var nameservers []net.IP var nameservers []net.IP
if netdata.DNS != nil { for _, v := range netdata.DNS.Nameservers {
nameservers = netdata.DNS nameservers = append(nameservers, net.ParseIP(v))
} else { }
if len(nameservers) == 0 {
nameservers = append(nameservers, net.ParseIP("8.8.8.8"), net.ParseIP("8.8.4.4")) nameservers = append(nameservers, net.ParseIP("8.8.8.8"), net.ParseIP("8.8.4.4"))
} }
@ -36,43 +37,44 @@ func ProcessPacketNetconf(netdata packet.NetworkData) ([]InterfaceGenerator, err
return generators, nil return generators, nil
} }
func parseNetwork(netdata packet.NetworkData, nameservers []net.IP) ([]InterfaceGenerator, error) { func parseNetwork(netdata netconf.NetworkConfig, nameservers []net.IP) ([]InterfaceGenerator, error) {
var interfaces []InterfaceGenerator var interfaces []InterfaceGenerator
var addresses []net.IPNet var addresses []net.IPNet
var routes []route var routes []route
for _, netblock := range netdata.Netblocks { /* for _, netblock := range netdata.Netblocks {
addresses = append(addresses, net.IPNet{ addresses = append(addresses, net.IPNet{
IP: netblock.Address, IP: netblock.Address,
Mask: net.IPMask(netblock.Netmask), Mask: net.IPMask(netblock.Netmask),
})
if netblock.Public == false {
routes = append(routes, route{
destination: net.IPNet{
IP: net.IPv4(10, 0, 0, 0),
Mask: net.IPv4Mask(255, 0, 0, 0),
},
gateway: netblock.Gateway,
}) })
} else { if netblock.Public == false {
if netblock.AddressFamily == 4 {
routes = append(routes, route{ routes = append(routes, route{
destination: net.IPNet{ destination: net.IPNet{
IP: net.IPv4zero, IP: net.IPv4(10, 0, 0, 0),
Mask: net.IPMask(net.IPv4zero), Mask: net.IPv4Mask(255, 0, 0, 0),
}, },
gateway: netblock.Gateway, gateway: netblock.Gateway,
}) })
} else { } else {
routes = append(routes, route{ if netblock.AddressFamily == 4 {
destination: net.IPNet{ routes = append(routes, route{
IP: net.IPv6zero, destination: net.IPNet{
Mask: net.IPMask(net.IPv6zero), IP: net.IPv4zero,
}, Mask: net.IPMask(net.IPv4zero),
gateway: netblock.Gateway, },
}) gateway: netblock.Gateway,
})
} else {
routes = append(routes, route{
destination: net.IPNet{
IP: net.IPv6zero,
Mask: net.IPMask(net.IPv6zero),
},
gateway: netblock.Gateway,
})
}
} }
} }
} */
bond := bondInterface{ bond := bondInterface{
logicalInterface: logicalInterface{ logicalInterface: logicalInterface{
@ -92,14 +94,15 @@ func parseNetwork(netdata packet.NetworkData, nameservers []net.IP) ([]Interface
}, },
} }
bond.hwaddr, _ = net.ParseMAC(netdata.Interfaces[0].Mac) //bond.hwaddr, _ = net.ParseMAC(netdata.Interfaces[0].Mac)
for index, iface := range netdata.Interfaces { index := 0
bond.slaves = append(bond.slaves, iface.Name) for name := range netdata.Interfaces {
bond.slaves = append(bond.slaves, name)
interfaces = append(interfaces, &physicalInterface{ interfaces = append(interfaces, &physicalInterface{
logicalInterface: logicalInterface{ logicalInterface: logicalInterface{
name: iface.Name, name: name,
config: configMethodStatic{ config: configMethodStatic{
nameservers: nameservers, nameservers: nameservers,
}, },
@ -107,6 +110,7 @@ func parseNetwork(netdata packet.NetworkData, nameservers []net.IP) ([]Interface
configDepth: index, configDepth: index,
}, },
}) })
index = index + 1
} }
interfaces = append(interfaces, &bond) interfaces = append(interfaces, &bond)

View File

@ -317,6 +317,7 @@ func readConfigFile(file string) ([]byte, error) {
} }
func substituteVars(userDataBytes []byte, metadata datasource.Metadata) []byte { func substituteVars(userDataBytes []byte, metadata datasource.Metadata) []byte {
// TODO: I think this currently does nothing - its hardcoded for COREOS env..
env := initialize.NewEnvironment("", "", "", "", metadata) env := initialize.NewEnvironment("", "", "", "", metadata)
userData := env.Apply(string(userDataBytes)) userData := env.Apply(string(userDataBytes))

44
config/types.go Normal file → Executable file
View File

@ -8,6 +8,7 @@ import (
composeConfig "github.com/docker/libcompose/config" composeConfig "github.com/docker/libcompose/config"
"github.com/rancher/os/config/cloudinit/config" "github.com/rancher/os/config/cloudinit/config"
"github.com/rancher/os/config/yaml" "github.com/rancher/os/config/yaml"
"github.com/rancher/os/netconf"
) )
const ( const (
@ -113,8 +114,8 @@ type RancherConfig struct {
Disable []string `yaml:"disable,omitempty"` Disable []string `yaml:"disable,omitempty"`
ServicesInclude map[string]bool `yaml:"services_include,omitempty"` ServicesInclude map[string]bool `yaml:"services_include,omitempty"`
Modules []string `yaml:"modules,omitempty"` Modules []string `yaml:"modules,omitempty"`
Network NetworkConfig `yaml:"network,omitempty"` Network netconf.NetworkConfig `yaml:"network,omitempty"`
DefaultNetwork NetworkConfig `yaml:"default_network,omitempty"` DefaultNetwork netconf.NetworkConfig `yaml:"default_network,omitempty"`
Repositories Repositories `yaml:"repositories,omitempty"` Repositories Repositories `yaml:"repositories,omitempty"`
SSH SSHConfig `yaml:"ssh,omitempty"` SSH SSHConfig `yaml:"ssh,omitempty"`
State StateConfig `yaml:"state,omitempty"` State StateConfig `yaml:"state,omitempty"`
@ -170,39 +171,6 @@ type DockerConfig struct {
Exec bool `yaml:"exec,omitempty"` Exec bool `yaml:"exec,omitempty"`
} }
type NetworkConfig struct {
PreCmds []string `yaml:"pre_cmds,omitempty"`
DNS DNSConfig `yaml:"dns,omitempty"`
Interfaces map[string]InterfaceConfig `yaml:"interfaces,omitempty"`
PostCmds []string `yaml:"post_cmds,omitempty"`
HTTPProxy string `yaml:"http_proxy,omitempty"`
HTTPSProxy string `yaml:"https_proxy,omitempty"`
NoProxy string `yaml:"no_proxy,omitempty"`
}
type InterfaceConfig struct {
Match string `yaml:"match,omitempty"`
DHCP bool `yaml:"dhcp,omitempty"`
DHCPArgs string `yaml:"dhcp_args,omitempty"`
Address string `yaml:"address,omitempty"`
Addresses []string `yaml:"addresses,omitempty"`
IPV4LL bool `yaml:"ipv4ll,omitempty"`
Gateway string `yaml:"gateway,omitempty"`
GatewayIpv6 string `yaml:"gateway_ipv6,omitempty"`
MTU int `yaml:"mtu,omitempty"`
Bridge string `yaml:"bridge,omitempty"`
Bond string `yaml:"bond,omitempty"`
BondOpts map[string]string `yaml:"bond_opts,omitempty"`
PostUp []string `yaml:"post_up,omitempty"`
PreUp []string `yaml:"pre_up,omitempty"`
Vlans string `yaml:"vlans,omitempty"`
}
type DNSConfig struct {
Nameservers []string `yaml:"nameservers,flow,omitempty"`
Search []string `yaml:"search,flow,omitempty"`
}
type SSHConfig struct { type SSHConfig struct {
Keys map[string]string `yaml:"keys,omitempty"` Keys map[string]string `yaml:"keys,omitempty"`
} }
@ -225,9 +193,9 @@ type CloudInit struct {
} }
type Defaults struct { type Defaults struct {
Hostname string `yaml:"hostname,omitempty"` Hostname string `yaml:"hostname,omitempty"`
Docker DockerConfig `yaml:"docker,omitempty"` Docker DockerConfig `yaml:"docker,omitempty"`
Network NetworkConfig `yaml:"network,omitempty"` Network netconf.NetworkConfig `yaml:"network,omitempty"`
} }
func (r Repositories) ToArray() []string { func (r Repositories) ToArray() []string {

View File

@ -12,7 +12,6 @@ import (
"syscall" "syscall"
"github.com/docker/libnetwork/resolvconf" "github.com/docker/libnetwork/resolvconf"
"github.com/rancher/os/config"
"github.com/rancher/os/log" "github.com/rancher/os/log"
"github.com/rancher/os/netconf" "github.com/rancher/os/netconf"
"github.com/rancher/os/selinux" "github.com/rancher/os/selinux"
@ -46,7 +45,7 @@ type Config struct {
Fork bool Fork bool
PidOne bool PidOne bool
CommandName string CommandName string
DNSConfig config.DNSConfig DNSConfig netconf.DNSConfig
BridgeName string BridgeName string
BridgeAddress string BridgeAddress string
BridgeMtu int BridgeMtu int
@ -359,8 +358,8 @@ ff02::2 ip6-allrouters
if cfg.BridgeName != "" && cfg.BridgeName != "none" { if cfg.BridgeName != "" && cfg.BridgeName != "none" {
log.Debugf("Creating bridge %s (%s)", cfg.BridgeName, cfg.BridgeAddress) log.Debugf("Creating bridge %s (%s)", cfg.BridgeName, cfg.BridgeAddress)
if err := netconf.ApplyNetworkConfigs(&config.NetworkConfig{ if err := netconf.ApplyNetworkConfigs(&netconf.NetworkConfig{
Interfaces: map[string]config.InterfaceConfig{ Interfaces: map[string]netconf.InterfaceConfig{
cfg.BridgeName: { cfg.BridgeName: {
Address: cfg.BridgeAddress, Address: cfg.BridgeAddress,
MTU: cfg.BridgeMtu, MTU: cfg.BridgeMtu,

View File

@ -13,7 +13,6 @@ import (
"github.com/flynn/go-shlex" "github.com/flynn/go-shlex"
"github.com/rancher/os/log" "github.com/rancher/os/log"
"github.com/rancher/os/config"
"github.com/ryanuber/go-glob" "github.com/ryanuber/go-glob"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
) )
@ -27,7 +26,7 @@ var (
defaultDhcpArgs = []string{"dhcpcd", "-MA4"} defaultDhcpArgs = []string{"dhcpcd", "-MA4"}
) )
func createInterfaces(netCfg *config.NetworkConfig) { func createInterfaces(netCfg *NetworkConfig) {
configured := map[string]bool{} configured := map[string]bool{}
for name, iface := range netCfg.Interfaces { for name, iface := range netCfg.Interfaces {
@ -65,7 +64,7 @@ func createInterfaces(netCfg *config.NetworkConfig) {
} }
} }
func createSlaveInterfaces(netCfg *config.NetworkConfig) { func createSlaveInterfaces(netCfg *NetworkConfig) {
links, err := netlink.LinkList() links, err := netlink.LinkList()
if err != nil { if err != nil {
log.Errorf("Failed to list links: %v", err) log.Errorf("Failed to list links: %v", err)
@ -92,9 +91,9 @@ func createSlaveInterfaces(netCfg *config.NetworkConfig) {
} }
} }
func findMatch(link netlink.Link, netCfg *config.NetworkConfig) (config.InterfaceConfig, bool) { func findMatch(link netlink.Link, netCfg *NetworkConfig) (InterfaceConfig, bool) {
linkName := link.Attrs().Name linkName := link.Attrs().Name
var match config.InterfaceConfig var match InterfaceConfig
exactMatch := false exactMatch := false
found := false found := false
@ -136,25 +135,25 @@ func findMatch(link netlink.Link, netCfg *config.NetworkConfig) (config.Interfac
return match, exactMatch || found return match, exactMatch || found
} }
func populateDefault(netCfg *config.NetworkConfig) { func populateDefault(netCfg *NetworkConfig) {
if netCfg.Interfaces == nil { if netCfg.Interfaces == nil {
netCfg.Interfaces = map[string]config.InterfaceConfig{} netCfg.Interfaces = map[string]InterfaceConfig{}
} }
if len(netCfg.Interfaces) == 0 { if len(netCfg.Interfaces) == 0 {
netCfg.Interfaces["eth*"] = config.InterfaceConfig{ netCfg.Interfaces["eth*"] = InterfaceConfig{
DHCP: true, DHCP: true,
} }
} }
if _, ok := netCfg.Interfaces["lo"]; !ok { if _, ok := netCfg.Interfaces["lo"]; !ok {
netCfg.Interfaces["lo"] = config.InterfaceConfig{ netCfg.Interfaces["lo"] = InterfaceConfig{
Address: "127.0.0.1/8", Address: "127.0.0.1/8",
} }
} }
} }
func ApplyNetworkConfigs(netCfg *config.NetworkConfig) error { func ApplyNetworkConfigs(netCfg *NetworkConfig) error {
populateDefault(netCfg) populateDefault(netCfg)
log.Debugf("Config: %#v", netCfg) log.Debugf("Config: %#v", netCfg)
@ -183,7 +182,7 @@ func ApplyNetworkConfigs(netCfg *config.NetworkConfig) error {
return err return err
} }
func RunDhcp(netCfg *config.NetworkConfig, setHostname, setDNS bool) error { func RunDhcp(netCfg *NetworkConfig, setHostname, setDNS bool) error {
populateDefault(netCfg) populateDefault(netCfg)
links, err := netlink.LinkList() links, err := netlink.LinkList()
@ -212,7 +211,7 @@ func RunDhcp(netCfg *config.NetworkConfig, setHostname, setDNS bool) error {
return err return err
} }
func runDhcp(netCfg *config.NetworkConfig, iface string, argstr string, setHostname, setDNS bool) { func runDhcp(netCfg *NetworkConfig, iface string, argstr string, setHostname, setDNS bool) {
log.Infof("Running DHCP on %s", iface) log.Infof("Running DHCP on %s", iface)
args := []string{} args := []string{}
if argstr != "" { if argstr != "" {
@ -243,7 +242,7 @@ func runDhcp(netCfg *config.NetworkConfig, iface string, argstr string, setHostn
} }
} }
func linkUp(link netlink.Link, netConf config.InterfaceConfig) error { func linkUp(link netlink.Link, netConf InterfaceConfig) error {
if err := netlink.LinkSetUp(link); err != nil { if err := netlink.LinkSetUp(link); err != nil {
log.Errorf("failed to setup link: %v", err) log.Errorf("failed to setup link: %v", err)
return err return err
@ -252,7 +251,7 @@ func linkUp(link netlink.Link, netConf config.InterfaceConfig) error {
return nil return nil
} }
func applyAddress(address string, link netlink.Link, netConf config.InterfaceConfig) error { func applyAddress(address string, link netlink.Link, netConf InterfaceConfig) error {
addr, err := netlink.ParseAddr(address) addr, err := netlink.ParseAddr(address)
if err != nil { if err != nil {
return err return err
@ -294,7 +293,7 @@ func setGateway(gateway string) error {
return nil return nil
} }
func applyInterfaceConfig(link netlink.Link, netConf config.InterfaceConfig) error { func applyInterfaceConfig(link netlink.Link, netConf InterfaceConfig) error {
if netConf.Bond != "" { if netConf.Bond != "" {
if err := netlink.LinkSetDown(link); err != nil { if err := netlink.LinkSetDown(link); err != nil {
return err return err

34
netconf/types.go Executable file
View File

@ -0,0 +1,34 @@
package netconf
type NetworkConfig struct {
PreCmds []string `yaml:"pre_cmds,omitempty"`
DNS DNSConfig `yaml:"dns,omitempty"`
Interfaces map[string]InterfaceConfig `yaml:"interfaces,omitempty"`
PostCmds []string `yaml:"post_cmds,omitempty"`
HTTPProxy string `yaml:"http_proxy,omitempty"`
HTTPSProxy string `yaml:"https_proxy,omitempty"`
NoProxy string `yaml:"no_proxy,omitempty"`
}
type InterfaceConfig struct {
Match string `yaml:"match,omitempty"`
DHCP bool `yaml:"dhcp,omitempty"`
DHCPArgs string `yaml:"dhcp_args,omitempty"`
Address string `yaml:"address,omitempty"`
Addresses []string `yaml:"addresses,omitempty"`
IPV4LL bool `yaml:"ipv4ll,omitempty"`
Gateway string `yaml:"gateway,omitempty"`
GatewayIpv6 string `yaml:"gateway_ipv6,omitempty"`
MTU int `yaml:"mtu,omitempty"`
Bridge string `yaml:"bridge,omitempty"`
Bond string `yaml:"bond,omitempty"`
BondOpts map[string]string `yaml:"bond_opts,omitempty"`
PostUp []string `yaml:"post_up,omitempty"`
PreUp []string `yaml:"pre_up,omitempty"`
Vlans string `yaml:"vlans,omitempty"`
}
type DNSConfig struct {
Nameservers []string `yaml:"nameservers,flow,omitempty"`
Search []string `yaml:"search,flow,omitempty"`
}

29
scripts/ros Executable file
View File

@ -0,0 +1,29 @@
#!/bin/bash
set -e
cd $(dirname $0)/..
if [ ! -e "./build/initrd/usr/share/ros/os-config.yml" ]; then
./.dapper release
else
echo "using existing build of ros"
# ./.dapper build-target
fi
source ./scripts/version
echo "---------------------------------"
echo "ln -s /usr/bin/ros /usr/bin/cloud-init-save"
echo "ros config set rancher.cloud_init.datasources [packet:https://metadata.packet.net/]"
#echo "ros config set rancher.cloud_init.datasources [packet:https://192.80.8.124/]"
echo "cloud-init-save"
echo "---------------------------------"
docker run --rm -it \
-v $(pwd)/build/initrd/usr/share:/usr/share \
-v $(pwd)/bin/ros:/usr/bin/ros \
-v /etc/ssl/certs:/etc/ssl/certs \
-v /usr/share/ca-certificates:/usr/share/ca-certificates \
-w /var/lib/rancher \
--entrypoint sh \
rancher/os-base:v0.8.1