Skip to content

Commit 0ea7d74

Browse files
committed
Hostname1 api
Add support for the systemd-hostnamed D-Bus interface. See: https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.hostname1.html Signed-off-by: Ananth Bhaskararaman <[email protected]>
1 parent 7d375ec commit 0ea7d74

File tree

3 files changed

+382
-8
lines changed

3 files changed

+382
-8
lines changed

hostname1/dbus.go

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
// Copyright 2015 CoreOS, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Package hostname1 provides integration with the systemd hostnamed API.
16+
// See https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.hostname1.html
17+
package hostname1
18+
19+
import (
20+
"os"
21+
"strconv"
22+
23+
"github.com/godbus/dbus/v5"
24+
)
25+
26+
const (
27+
dbusDest = "org.freedesktop.hostname1"
28+
dbusPath = "/org/freedesktop/hostname1"
29+
)
30+
31+
// Conn is a connection to systemds dbus endpoint.
32+
type Conn struct {
33+
conn *dbus.Conn
34+
object dbus.BusObject
35+
}
36+
37+
// New establishes a connection to the system bus and authenticates.
38+
func New() (*Conn, error) {
39+
c := new(Conn)
40+
41+
if err := c.initConnection(); err != nil {
42+
return nil, err
43+
}
44+
45+
return c, nil
46+
}
47+
48+
// Close closes the dbus connection
49+
func (c *Conn) Close() {
50+
if c == nil {
51+
return
52+
}
53+
54+
if c.conn != nil {
55+
c.conn.Close()
56+
}
57+
}
58+
59+
// Connected returns whether conn is connected
60+
func (c *Conn) Connected() bool {
61+
return c.conn.Connected()
62+
}
63+
64+
func (c *Conn) initConnection() error {
65+
var err error
66+
if c.conn, err = dbus.SystemBusPrivate(); err != nil {
67+
return err
68+
}
69+
70+
// Only use EXTERNAL method, and hardcode the uid (not username)
71+
// to avoid a username lookup (which requires a dynamically linked
72+
// libc)
73+
methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))}
74+
75+
if err := c.conn.Auth(methods); err != nil {
76+
c.conn.Close()
77+
return err
78+
}
79+
80+
if err := c.conn.Hello(); err != nil {
81+
c.conn.Close()
82+
return err
83+
}
84+
85+
c.object = c.conn.Object(dbusDest, dbus.ObjectPath(dbusPath))
86+
87+
return nil
88+
}
89+
90+
func (c *Conn) SetHostname(hostname string, interactive bool) error {
91+
return c.object.Call(dbusDest+".SetHostname", 0, hostname, interactive).Err
92+
}
93+
94+
func (c *Conn) SetStaticHostname(hostname string, interactive bool) error {
95+
return c.object.Call(dbusDest+".SetStaticHostname", 0, hostname, interactive).Err
96+
}
97+
98+
func (c *Conn) SetPrettyHostname(hostname string, interactive bool) error {
99+
return c.object.Call(dbusDest+".SetPrettyHostname", 0, hostname, interactive).Err
100+
}
101+
102+
func (c *Conn) SetIconName(iconName string, interactive bool) error {
103+
return c.object.Call(dbusDest+".SetIconName", 0, iconName, interactive).Err
104+
}
105+
106+
func (c *Conn) SetChassis(chassis string, interactive bool) error {
107+
return c.object.Call(dbusDest+".SetChassis", 0, chassis, interactive).Err
108+
}
109+
110+
func (c *Conn) SetDeployment(deployment string, interactive bool) error {
111+
return c.object.Call(dbusDest+".SetDeployment", 0, deployment, interactive).Err
112+
}
113+
114+
func (c *Conn) SetLocation(location string, interactive bool) error {
115+
return c.object.Call(dbusDest+".SetLocation", 0, location, interactive).Err
116+
}
117+
118+
func (c *Conn) GetProductUUID(interactive bool) ([]byte, error) {
119+
var uuid []byte
120+
err := c.object.Call(dbusDest+".GetProductUUID", 0, interactive).Store(&uuid)
121+
return uuid, err
122+
}
123+
124+
func (c *Conn) GetHardwareSerial() (string, error) {
125+
var serial string
126+
err := c.object.Call(dbusDest+".GetHardwareSerial", 0).Store(&serial)
127+
return serial, err
128+
}
129+
130+
func (c *Conn) Describe() (string, error) {
131+
var description string
132+
err := c.object.Call(dbusDest+".Describe", 0).Store(&description)
133+
return description, err
134+
}
135+
136+
func (c *Conn) Hostname() (string, error) {
137+
out, err := c.object.GetProperty(dbusDest + ".Hostname")
138+
if err != nil {
139+
return "", err
140+
}
141+
return out.Value().(string), nil
142+
}
143+
144+
func (c *Conn) StaticHostname() (string, error) {
145+
out, err := c.object.GetProperty(dbusDest + ".StaticHostname")
146+
if err != nil {
147+
return "", err
148+
}
149+
return out.Value().(string), nil
150+
}
151+
152+
func (c *Conn) PrettyHostname() (string, error) {
153+
out, err := c.object.GetProperty(dbusDest + ".PrettyHostname")
154+
if err != nil {
155+
return "", err
156+
}
157+
return out.Value().(string), nil
158+
}
159+
160+
func (c *Conn) DefaultHostname() (string, error) {
161+
out, err := c.object.GetProperty(dbusDest + ".DefaultHostname")
162+
if err != nil {
163+
return "", err
164+
}
165+
return out.Value().(string), nil
166+
}
167+
168+
func (c *Conn) HostnameSource() (string, error) {
169+
out, err := c.object.GetProperty(dbusDest + ".HostnameSource")
170+
if err != nil {
171+
return "", err
172+
}
173+
return out.Value().(string), nil
174+
}
175+
176+
func (c *Conn) IconName() (string, error) {
177+
out, err := c.object.GetProperty(dbusDest + ".IconName")
178+
if err != nil {
179+
return "", err
180+
}
181+
return out.Value().(string), nil
182+
}
183+
184+
func (c *Conn) Chassis() (string, error) {
185+
out, err := c.object.GetProperty(dbusDest + ".Chassis")
186+
if err != nil {
187+
return "", err
188+
}
189+
return out.Value().(string), nil
190+
}
191+
192+
func (c *Conn) Deployment() (string, error) {
193+
out, err := c.object.GetProperty(dbusDest + ".Deployment")
194+
if err != nil {
195+
return "", err
196+
}
197+
return out.Value().(string), nil
198+
}
199+
200+
func (c *Conn) Location() (string, error) {
201+
out, err := c.object.GetProperty(dbusDest + ".Location")
202+
if err != nil {
203+
return "", err
204+
}
205+
return out.Value().(string), nil
206+
}
207+
208+
func (c *Conn) KernelName() (string, error) {
209+
out, err := c.object.GetProperty(dbusDest + ".KernelName")
210+
if err != nil {
211+
return "", err
212+
}
213+
return out.Value().(string), nil
214+
}
215+
216+
func (c *Conn) KernelRelease() (string, error) {
217+
out, err := c.object.GetProperty(dbusDest + ".KernelRelease")
218+
if err != nil {
219+
return "", err
220+
}
221+
return out.Value().(string), nil
222+
}
223+
224+
func (c *Conn) KernelVersion() (string, error) {
225+
out, err := c.object.GetProperty(dbusDest + ".KernelVersion")
226+
if err != nil {
227+
return "", err
228+
}
229+
return out.Value().(string), nil
230+
}
231+
232+
func (c *Conn) OperatingSystemPrettyName() (string, error) {
233+
out, err := c.object.GetProperty(dbusDest + ".OperatingSystemPrettyName")
234+
if err != nil {
235+
return "", err
236+
}
237+
return out.Value().(string), nil
238+
}
239+
240+
func (c *Conn) OperatingSystemCPEName() (string, error) {
241+
out, err := c.object.GetProperty(dbusDest + ".OperatingSystemCPEName")
242+
if err != nil {
243+
return "", err
244+
}
245+
return out.Value().(string), nil
246+
}
247+
248+
func (c *Conn) OperatingSystemSupportEnd() (uint64, error) {
249+
out, err := c.object.GetProperty(dbusDest + ".OperatingSystemSupportEnd")
250+
if err != nil {
251+
return 0, err
252+
}
253+
return out.Value().(uint64), nil
254+
}
255+
256+
func (c *Conn) HomeURL() (string, error) {
257+
out, err := c.object.GetProperty(dbusDest + ".HomeURL")
258+
if err != nil {
259+
return "", err
260+
}
261+
return out.Value().(string), nil
262+
}
263+
264+
func (c *Conn) HardwareVendor() (string, error) {
265+
out, err := c.object.GetProperty(dbusDest + ".HardwareVendor")
266+
if err != nil {
267+
return "", err
268+
}
269+
return out.Value().(string), nil
270+
}
271+
272+
func (c *Conn) HardwareModel() (string, error) {
273+
out, err := c.object.GetProperty(dbusDest + ".HardwareModel")
274+
if err != nil {
275+
return "", err
276+
}
277+
return out.Value().(string), nil
278+
}
279+
280+
func (c *Conn) FirmwareVersion() (string, error) {
281+
out, err := c.object.GetProperty(dbusDest + ".FirmwareVersion")
282+
if err != nil {
283+
return "", err
284+
}
285+
return out.Value().(string), nil
286+
}
287+
288+
func (c *Conn) FirmwareVendor() (string, error) {
289+
out, err := c.object.GetProperty(dbusDest + ".FirmwareVendor")
290+
if err != nil {
291+
return "", err
292+
}
293+
return out.Value().(string), nil
294+
}
295+
296+
func (c *Conn) FirmwareDate() (uint64, error) {
297+
out, err := c.object.GetProperty(dbusDest + ".FirmwareDate")
298+
if err != nil {
299+
return 0, err
300+
}
301+
return out.Value().(uint64), nil
302+
}

hostname1/dbus_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2015 CoreOS, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package hostname1
15+
16+
import (
17+
"io"
18+
"os"
19+
"os/exec"
20+
"strings"
21+
"testing"
22+
)
23+
24+
// TestNew ensures that New() works without errors.
25+
func TestNew(t *testing.T) {
26+
if _, err := New(); err != nil {
27+
t.Fatal(err)
28+
}
29+
}
30+
31+
// TestHostname ensures that the Hostname() method returns the system hostname.
32+
func TestHostname(t *testing.T) {
33+
expectedHostname, err := exec.Command("hostname").CombinedOutput()
34+
if err != nil {
35+
t.Fatal(err)
36+
}
37+
38+
h, err := New()
39+
if err != nil {
40+
t.Fatal(err)
41+
}
42+
43+
if hostname, err := h.Hostname(); err != nil {
44+
t.Fatal(err)
45+
} else if hostname != strings.TrimSuffix(string(expectedHostname), "\n") {
46+
t.Fatalf("expected %q, got %q", expectedHostname, hostname)
47+
}
48+
}
49+
50+
func TestStaticHostname(t *testing.T) {
51+
hostnameFile, err := os.Open("/etc/hostname")
52+
if err != nil {
53+
t.Fatal(err)
54+
}
55+
defer hostnameFile.Close()
56+
57+
expectedHostnameBytes := make([]byte, 256)
58+
n, err := hostnameFile.Read(expectedHostnameBytes)
59+
if err != nil && err != io.EOF {
60+
t.Fatal(err)
61+
}
62+
// Close the file so that hostnamed can use it.
63+
hostnameFile.Close()
64+
expectedHostname := strings.TrimSuffix(string(expectedHostnameBytes[:n]), "\n")
65+
66+
h, err := New()
67+
if err != nil {
68+
t.Fatal(err)
69+
}
70+
71+
if hostname, err := h.StaticHostname(); err != nil {
72+
t.Fatal(err)
73+
} else if hostname != expectedHostname {
74+
t.Fatalf("expected %q, got %q", expectedHostname, hostname)
75+
}
76+
}

0 commit comments

Comments
 (0)