cloudinit/system/systemd.go

184 lines
3.5 KiB
Go
Raw Normal View History

2014-03-18 09:00:41 -07:00
package system
2014-03-04 16:36:05 -08:00
import (
"fmt"
"io/ioutil"
2014-03-04 16:36:05 -08:00
"log"
2014-03-12 15:43:51 -07:00
"os"
"os/exec"
2014-03-04 16:36:05 -08:00
"path"
2014-03-12 15:43:51 -07:00
"path/filepath"
"strings"
2014-03-04 16:36:05 -08:00
2014-03-12 19:36:31 -07:00
"github.com/coreos/coreos-cloudinit/third_party/github.com/coreos/go-systemd/dbus"
2014-03-04 16:36:05 -08:00
)
// fakeMachineID is placed on non-usr CoreOS images and should
// never be used as a true MachineID
const fakeMachineID = "42000000000000000000000000000042"
2014-03-12 15:43:51 -07:00
type Unit struct {
Name string
Runtime bool
Content string
}
func (u *Unit) Type() string {
ext := filepath.Ext(u.Name)
return strings.TrimLeft(ext, ".")
}
func (u *Unit) Group() (group string) {
t := u.Type()
if t == "network" || t == "netdev" || t == "link" {
group = "network"
} else {
group = "system"
}
return
}
2014-03-04 16:36:05 -08:00
type Script []byte
2014-03-18 09:00:41 -07:00
func PlaceUnit(u *Unit, root string) (string, error) {
2014-03-12 15:43:51 -07:00
dir := "etc"
if u.Runtime {
dir = "run"
}
dst := path.Join(root, dir, "systemd", u.Group())
if _, err := os.Stat(dst); os.IsNotExist(err) {
if err := os.MkdirAll(dst, os.FileMode(0755)); err != nil {
return "", err
}
}
dst = path.Join(dst, u.Name)
2014-03-18 09:00:41 -07:00
file := File{
Path: dst,
Content: u.Content,
RawFilePermissions: "0644",
}
err := WriteFile(&file)
2014-03-12 15:43:51 -07:00
if err != nil {
return "", err
}
return dst, nil
}
func EnableUnitFile(file string, runtime bool) error {
conn, err := dbus.New()
if err != nil {
return err
}
files := []string{file}
_, _, err = conn.EnableUnitFiles(files, runtime, true)
return err
}
func separateNetworkUnits(units []Unit) ([]Unit, []Unit) {
networkUnits := make([]Unit, 0)
nonNetworkUnits := make([]Unit, 0)
for _, unit := range units {
if unit.Group() == "network" {
networkUnits = append(networkUnits, unit)
} else {
nonNetworkUnits = append(nonNetworkUnits, unit)
}
}
return networkUnits, nonNetworkUnits
}
func StartUnits(units []Unit) error {
networkUnits, nonNetworkUnits := separateNetworkUnits(units)
if len(networkUnits) > 0 {
if err := RestartUnitByName("systemd-networkd.service"); err != nil {
return err
}
}
for _, unit := range nonNetworkUnits {
if err := RestartUnitByName(unit.Name); err != nil {
return err
}
}
return nil
}
func DaemonReload() error {
conn, err := dbus.New()
if err != nil {
return err
}
_, err = conn.Reload()
return err
}
func RestartUnitByName(name string) error {
log.Printf("Restarting unit %s", name)
conn, err := dbus.New()
if err != nil {
return err
}
2014-03-12 22:04:08 -07:00
output, err := conn.RestartUnit(name, "replace")
2014-03-12 21:47:01 -07:00
log.Printf("Restart completed with '%s'", output)
2014-03-12 15:43:51 -07:00
return err
}
func StartUnitByName(name string) error {
2014-03-04 16:36:05 -08:00
conn, err := dbus.New()
if err != nil {
return err
}
_, err = conn.StartUnit(name, "replace")
return err
}
func ExecuteScript(scriptPath string) (string, error) {
2014-03-04 16:36:05 -08:00
props := []dbus.Property{
dbus.PropDescription("Unit generated and executed by coreos-cloudinit on behalf of user"),
2014-03-04 16:36:05 -08:00
dbus.PropExecStart([]string{"/bin/bash", scriptPath}, false),
}
base := path.Base(scriptPath)
name := fmt.Sprintf("coreos-cloudinit-%s.service", base)
2014-03-04 16:36:05 -08:00
log.Printf("Creating transient systemd unit '%s'", name)
conn, err := dbus.New()
if err != nil {
return "", err
2014-03-04 16:36:05 -08:00
}
_, err = conn.StartTransientUnit(name, "replace", props...)
return name, err
2014-03-04 16:36:05 -08:00
}
func SetHostname(hostname string) error {
return exec.Command("hostnamectl", "set-hostname", hostname).Run()
}
func Hostname() (string, error) {
2014-03-18 11:04:33 -07:00
return os.Hostname()
}
func MachineID(root string) string {
contents, _ := ioutil.ReadFile(path.Join(root, "etc", "machine-id"))
id := strings.TrimSpace(string(contents))
if id == fakeMachineID {
id = ""
}
return id
}