Compare commits

..

13 Commits

Author SHA1 Message Date
Alex Crawford
f3f3af79fd coreos-cloudinit: bump to v1.0.1 2014-12-04 16:34:57 -08:00
Alex Crawford
0e63aa0f6b Merge pull request #276 from crawford/networkd
initialize: restart networkd before other units
2014-12-04 16:33:02 -08:00
Alex Crawford
b254e17e89 Merge pull request #263 from robszumski/docs-validator
docs: link to validator
2014-12-04 16:28:21 -08:00
Alex Crawford
5c059b66f0 initialize: restart networkd before other units 2014-12-04 15:25:44 -08:00
Alex Crawford
c628bef666 Merge pull request #273 from crawford/networkd
initialize: only restart networkd once per config
2014-12-02 12:54:27 -08:00
Alex Crawford
2270db3f7a initialize: only restart networkd once per config
Regression introduced by 9fcf338bf3.

Networkd was erroneously being restarted once per network unit. It
should only restart once for the entire config.
2014-12-02 12:46:35 -08:00
Alex Crawford
d0d467813d Merge pull request #251 from Vladimiroff/master
metadata: Populate CloudSigma's IPs properly
2014-12-01 14:52:11 -08:00
Alex Crawford
123f111efe coreos-cloudinit: bump to 1.0.0+git 2014-11-26 14:19:29 -08:00
Rob Szumski
44fdf95d99 docs: mention validate flag 2014-11-20 11:12:31 -08:00
Rob Szumski
0a62614eec docs: link to validator 2014-11-20 10:58:57 -08:00
Kiril Vladimirov
ea95920f31 fix(datasource/CloudSigma): Make sure DHCP has run 2014-11-17 15:35:10 +02:00
Kiril Vladimirov
b6062f0644 fix(datasource/CloudSigma): Populate local IPv4 address properly 2014-10-23 15:03:23 +03:00
Kiril Vladimirov
c5fada6e69 fix(datasource/CloudSigma): Populate public IPv4 address properly 2014-10-23 13:21:49 +03:00
6 changed files with 129 additions and 32 deletions

View File

@@ -1,6 +1,8 @@
# Using Cloud-Config # Using Cloud-Config
CoreOS allows you to declaratively customize various OS-level items, such as network configuration, user accounts, and systemd units. This document describes the full list of items we can configure. The `coreos-cloudinit` program uses these files as it configures the OS after startup or during runtime. Your cloud-config is processed during each boot. CoreOS allows you to declaratively customize various OS-level items, such as network configuration, user accounts, and systemd units. This document describes the full list of items we can configure. The `coreos-cloudinit` program uses these files as it configures the OS after startup or during runtime.
Your cloud-config is processed during each boot. Invalid cloud-config won't be processed but will be logged in the journal. You can validate your cloud-config with the [CoreOS validator]({{site.url}}/validate) or by running `coreos-cloudinit -validate`.
## Configuration File ## Configuration File

View File

@@ -40,7 +40,7 @@ import (
) )
const ( const (
version = "1.0.0" version = "1.0.1"
datasourceInterval = 100 * time.Millisecond datasourceInterval = 100 * time.Millisecond
datasourceMaxInterval = 30 * time.Second datasourceMaxInterval = 30 * time.Second
datasourceTimeout = 5 * time.Minute datasourceTimeout = 5 * time.Minute

View File

@@ -17,8 +17,12 @@
package cloudsigma package cloudsigma
import ( import (
"bytes"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"io/ioutil"
"net"
"os" "os"
"strings" "strings"
@@ -51,7 +55,8 @@ func (_ *serverContextService) IsAvailable() bool {
} }
productName := make([]byte, 10) productName := make([]byte, 10)
_, err = productNameFile.Read(productName) _, err = productNameFile.Read(productName)
return err == nil && string(productName) == "CloudSigma"
return err == nil && string(productName) == "CloudSigma" && hasDHCPLeases()
} }
func (_ *serverContextService) AvailabilityChanges() bool { func (_ *serverContextService) AvailabilityChanges() bool {
@@ -73,12 +78,16 @@ func (scs *serverContextService) FetchMetadata() ([]byte, error) {
UUID string `json:"uuid"` UUID string `json:"uuid"`
Meta map[string]string `json:"meta"` Meta map[string]string `json:"meta"`
Nics []struct { Nics []struct {
Runtime struct { Mac string `json:"mac"`
IPv4Conf struct {
InterfaceType string `json:"interface_type"` InterfaceType string `json:"interface_type"`
IPv4 struct { IP struct {
IP string `json:"uuid"` UUID string `json:"uuid"`
} `json:"ip_v4"` } `json:"ip"`
} `json:"runtime"` } `json:"ip_v4_conf"`
VLAN struct {
UUID string `json:"uuid"`
} `json:"vlan"`
} `json:"nics"` } `json:"nics"`
} }
outputMetadata struct { outputMetadata struct {
@@ -112,11 +121,12 @@ func (scs *serverContextService) FetchMetadata() ([]byte, error) {
} }
for _, nic := range inputMetadata.Nics { for _, nic := range inputMetadata.Nics {
if nic.Runtime.IPv4.IP != "" { if nic.IPv4Conf.IP.UUID != "" {
if nic.Runtime.InterfaceType == "public" { outputMetadata.PublicIPv4 = nic.IPv4Conf.IP.UUID
outputMetadata.PublicIPv4 = nic.Runtime.IPv4.IP }
} else { if nic.VLAN.UUID != "" {
outputMetadata.LocalIPv4 = nic.Runtime.IPv4.IP if localIP, err := scs.findLocalIP(nic.Mac); err == nil {
outputMetadata.LocalIPv4 = localIP
} }
} }
} }
@@ -146,6 +156,36 @@ func (scs *serverContextService) FetchNetworkConfig(a string) ([]byte, error) {
return nil, nil return nil, nil
} }
func (scs *serverContextService) findLocalIP(mac string) (string, error) {
ifaces, err := net.Interfaces()
if err != nil {
return "", err
}
ifaceMac, err := net.ParseMAC(mac)
if err != nil {
return "", err
}
for _, iface := range ifaces {
if !bytes.Equal(iface.HardwareAddr, ifaceMac) {
continue
}
addrs, err := iface.Addrs()
if err != nil {
continue
}
for _, addr := range addrs {
switch ip := addr.(type) {
case *net.IPNet:
if ip.IP.To4() != nil {
return ip.IP.To4().String(), nil
}
}
}
}
return "", errors.New("Local IP not found")
}
func isBase64Encoded(field string, userdata map[string]string) bool { func isBase64Encoded(field string, userdata map[string]string) bool {
base64Fields, ok := userdata["base64_fields"] base64Fields, ok := userdata["base64_fields"]
if !ok { if !ok {
@@ -159,3 +199,8 @@ func isBase64Encoded(field string, userdata map[string]string) bool {
} }
return false return false
} }
func hasDHCPLeases() bool {
files, err := ioutil.ReadDir("/run/systemd/netif/leases/")
return err == nil && len(files) > 0
}

View File

@@ -74,14 +74,41 @@ func TestServerContextFetchMetadata(t *testing.T) {
"name": "coreos", "name": "coreos",
"nics": [ "nics": [
{ {
"runtime": { "boot_order": null,
"interface_type": "public", "ip_v4_conf": {
"ip_v4": { "conf": "dhcp",
"ip": {
"gateway": "31.171.244.1",
"meta": {},
"nameservers": [
"178.22.66.167",
"178.22.71.56",
"8.8.8.8"
],
"netmask": 22,
"tags": [],
"uuid": "31.171.251.74" "uuid": "31.171.251.74"
}, }
"ip_v6": null
}, },
"ip_v6_conf": null,
"mac": "22:3d:09:6b:90:f3",
"model": "virtio",
"vlan": null "vlan": null
},
{
"boot_order": null,
"ip_v4_conf": null,
"ip_v6_conf": null,
"mac": "22:ae:4a:fb:8f:31",
"model": "virtio",
"vlan": {
"meta": {
"description": "",
"name": "CoreOS"
},
"tags": [],
"uuid": "5dec030e-25b8-4621-a5a4-a3302c9d9619"
}
} }
], ],
"smp": 2, "smp": 2,
@@ -106,12 +133,8 @@ func TestServerContextFetchMetadata(t *testing.T) {
t.Error("Public SSH Keys are not being read properly") t.Error("Public SSH Keys are not being read properly")
} }
if metadata.LocalIPv4 != "" {
t.Errorf("Local IP is not empty but %s instead", metadata.LocalIPv4)
}
if metadata.PublicIPv4 != "31.171.251.74" { if metadata.PublicIPv4 != "31.171.251.74" {
t.Errorf("Local IP is not 31.171.251.74 but %s instead", metadata.PublicIPv4) t.Errorf("Public IP is not 31.171.251.74 but %s instead", metadata.PublicIPv4)
} }
} }

View File

@@ -200,6 +200,7 @@ func processUnits(units []system.Unit, root string, um system.UnitManager) error
} }
actions := make([]action, 0, len(units)) actions := make([]action, 0, len(units))
reload := false reload := false
restartNetworkd := false
for _, unit := range units { for _, unit := range units {
if unit.Name == "" { if unit.Name == "" {
log.Printf("Skipping unit without name") log.Printf("Skipping unit without name")
@@ -251,8 +252,7 @@ func processUnits(units []system.Unit, root string, um system.UnitManager) error
} }
if unit.Group() == "network" { if unit.Group() == "network" {
networkd := system.Unit{Unit: config.Unit{Name: "systemd-networkd.service"}} restartNetworkd = true
actions = append(actions, action{networkd, "restart"})
} else if unit.Command != "" { } else if unit.Command != "" {
actions = append(actions, action{unit, unit.Command}) actions = append(actions, action{unit, unit.Command})
} }
@@ -264,13 +264,23 @@ func processUnits(units []system.Unit, root string, um system.UnitManager) error
} }
} }
if restartNetworkd {
log.Printf("Restarting systemd-networkd")
networkd := system.Unit{Unit: config.Unit{Name: "systemd-networkd.service"}}
res, err := um.RunUnitCommand(networkd, "restart")
if err != nil {
return err
}
log.Printf("Restarted systemd-networkd (%s)", res)
}
for _, action := range actions { for _, action := range actions {
log.Printf("Calling unit command %q on %q'", action.command, action.unit.Name) log.Printf("Calling unit command %q on %q'", action.command, action.unit.Name)
res, err := um.RunUnitCommand(action.unit, action.command) res, err := um.RunUnitCommand(action.unit, action.command)
if err != nil { if err != nil {
return err return err
} }
log.Printf("Result of %q on %q': %s", action.command, action.unit.Name, res) log.Printf("Result of %q on %q: %s", action.command, action.unit.Name, res)
} }
return nil return nil

View File

@@ -29,10 +29,15 @@ type TestUnitManager struct {
enabled []string enabled []string
masked []string masked []string
unmasked []string unmasked []string
commands map[string]string commands []UnitAction
reload bool reload bool
} }
type UnitAction struct {
unit string
command string
}
func (tum *TestUnitManager) PlaceUnit(u system.Unit) error { func (tum *TestUnitManager) PlaceUnit(u system.Unit) error {
tum.placed = append(tum.placed, u.Name) tum.placed = append(tum.placed, u.Name)
return nil return nil
@@ -46,8 +51,7 @@ func (tum *TestUnitManager) EnableUnitFile(u system.Unit) error {
return nil return nil
} }
func (tum *TestUnitManager) RunUnitCommand(u system.Unit, c string) (string, error) { func (tum *TestUnitManager) RunUnitCommand(u system.Unit, c string) (string, error) {
tum.commands = make(map[string]string) tum.commands = append(tum.commands, UnitAction{u.Name, c})
tum.commands[u.Name] = c
return "", nil return "", nil
} }
func (tum *TestUnitManager) DaemonReload() error { func (tum *TestUnitManager) DaemonReload() error {
@@ -83,13 +87,26 @@ func TestProcessUnits(t *testing.T) {
{ {
units: []system.Unit{ units: []system.Unit{
system.Unit{Unit: config.Unit{ system.Unit{Unit: config.Unit{
Name: "bar.network", Name: "baz.service",
Content: "[Service]\nExecStart=/bin/baz",
Command: "start",
}},
system.Unit{Unit: config.Unit{
Name: "foo.network",
Content: "[Network]\nFoo=true",
}},
system.Unit{Unit: config.Unit{
Name: "bar.network",
Content: "[Network]\nBar=true",
}}, }},
}, },
result: TestUnitManager{ result: TestUnitManager{
commands: map[string]string{ placed: []string{"baz.service", "foo.network", "bar.network"},
"systemd-networkd.service": "restart", commands: []UnitAction{
UnitAction{"systemd-networkd.service", "restart"},
UnitAction{"baz.service", "start"},
}, },
reload: true,
}, },
}, },
{ {