diff --git a/cmd/cloudinit/cloudinit.go b/cmd/cloudinit/cloudinit.go index d52a7630..9eb0658f 100644 --- a/cmd/cloudinit/cloudinit.go +++ b/cmd/cloudinit/cloudinit.go @@ -34,6 +34,7 @@ import ( "github.com/coreos/coreos-cloudinit/datasource/file" "github.com/coreos/coreos-cloudinit/datasource/metadata/digitalocean" "github.com/coreos/coreos-cloudinit/datasource/metadata/ec2" + "github.com/coreos/coreos-cloudinit/datasource/metadata/packet" "github.com/coreos/coreos-cloudinit/datasource/proc_cmdline" "github.com/coreos/coreos-cloudinit/datasource/url" "github.com/coreos/coreos-cloudinit/pkg" @@ -288,6 +289,11 @@ func getDatasources(cfg *rancherConfig.CloudConfig) []datasource.Datasource { } dss = append(dss, file.NewDatasource(gceCloudConfigFile)) } + case "packet": + if !network { + enablePacketNetwork(&cfg.Rancher) + } + dss = append(dss, packet.NewDatasource("https://metadata.packet.net/")) } } diff --git a/cmd/cloudinit/packet.go b/cmd/cloudinit/packet.go new file mode 100644 index 00000000..fb4fbc39 --- /dev/null +++ b/cmd/cloudinit/packet.go @@ -0,0 +1,89 @@ +package cloudinit + +import ( + "fmt" + "net/http" + "strings" + + "gopkg.in/yaml.v2" + + "github.com/Sirupsen/logrus" + "github.com/packethost/packngo/metadata" + "github.com/rancher/netconf" + rancherConfig "github.com/rancher/os/config" +) + +func enablePacketNetwork(cfg *rancherConfig.RancherConfig) { + bootStrapped := false + for _, v := range cfg.Network.Interfaces { + if v.Address != "" { + if err := netconf.ApplyNetworkConfigs(&cfg.Network); err != nil { + logrus.Errorf("Failed to bootstrap network: %v", err) + return + } + bootStrapped = true + break + } + } + + if !bootStrapped { + return + } + + c := metadata.NewClient(http.DefaultClient) + m, err := c.Metadata.Get() + if err != nil { + logrus.Errorf("Failed to get Packet metadata: %v", err) + return + } + + bondCfg := netconf.InterfaceConfig{ + 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{ + Interfaces: map[string]netconf.InterfaceConfig{}, + } + for _, iface := range m.Network.Interfaces { + netCfg.Interfaces["mac="+iface.Mac] = netconf.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) + } + } + + netCfg.Interfaces["bond0"] = bondCfg + bytes, _ := yaml.Marshal(netCfg) + logrus.Debugf("Generated network config: %s", string(bytes)) + + cc := rancherConfig.CloudConfig{ + Rancher: rancherConfig.RancherConfig{ + Network: netCfg, + }, + } + + if err := rancherConfig.WriteToFile(cc, rancherConfig.CloudConfigNetworkFile); err != nil { + logrus.Errorf("Failed to save config file %s: %v", rancherConfig.CloudConfigNetworkFile, err) + } +} diff --git a/config/types.go b/config/types.go index c252b524..a5461127 100644 --- a/config/types.go +++ b/config/types.go @@ -35,6 +35,7 @@ const ( CloudConfigDir = "/var/lib/rancher/conf/cloud-config.d" CloudConfigBootFile = "/var/lib/rancher/conf/cloud-config.d/boot.yml" CloudConfigPrivateFile = "/var/lib/rancher/conf/cloud-config.d/private.yml" + CloudConfigNetworkFile = "/var/lib/rancher/conf/cloud-config.d/network.yml" CloudConfigScriptFile = "/var/lib/rancher/conf/cloud-config-script" MetaDataFile = "/var/lib/rancher/conf/metadata" CloudConfigFile = "/var/lib/rancher/conf/cloud-config.yml"