X Tutup
Skip to content

Commit 1cd71df

Browse files
committed
systemd properties: support for *Sec values
Some systemd properties are documented as having "Sec" suffix (e.g. "TimeoutStopSec") but are expected to have "USec" suffix when passed over dbus, so let's provide appropriate conversion to improve compatibility. This means, one can specify TimeoutStopSec with a numeric argument, in seconds, and it will be properly converted to TimeoutStopUsec with the argument in microseconds. As a side bonus, even float values are converted, so e.g. TimeoutStopSec=1.5 is possible. This turned out a bit more tricky to implement when I was originally expected, since there are a handful of numeric types in dbus and each one requires explicit conversion. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
1 parent 2a81236 commit 1cd71df

File tree

3 files changed

+96
-8
lines changed

3 files changed

+96
-8
lines changed

docs/systemd-properties.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,4 @@ The values must be in the gvariant format (for details, see
2424
[gvariant documentation](https://developer.gnome.org/glib/stable/gvariant-text.html)).
2525

2626
To find out which type systemd expects for a particular parameter, please
27-
consult systemd sources. In particular, parameters with `USec` suffix are
28-
in microseconds, and those require an `uint64` typed argument. Since
29-
gvariant assumes int32 for a numeric values, the explicit type is required.
30-
31-
**Note** that time-typed systemd parameter names must have the `USec`
32-
suffix, while they are documented with `Sec` suffix.
33-
For example, the stop timeout used in the example above must be
34-
set as `TimeoutStopUSec` but is shown and documented as `TimeoutStopSec`.
27+
consult systemd sources.

libcontainer/specconv/spec_linux.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package specconv
66

77
import (
8+
"errors"
89
"fmt"
910
"os"
1011
"path/filepath"
@@ -304,6 +305,38 @@ func createLibcontainerMount(cwd string, m specs.Mount) *configs.Mount {
304305
// systemd property name check: latin letters only, at least 3 of them
305306
var isValidName = regexp.MustCompile(`^[a-zA-Z]{3,}$`).MatchString
306307

308+
var isSecSuffix = regexp.MustCompile(`[a-z]Sec$`).MatchString
309+
310+
// Some systemd properties are documented as having "Sec" suffix
311+
// (e.g. TimeoutStopSec) but are expected to have "USec" suffix
312+
// here, so let's provide conversion to improve compatibility.
313+
func convertSecToUSec(value dbus.Variant) (dbus.Variant, error) {
314+
var sec uint64
315+
const M = 1000000
316+
vi := value.Value()
317+
switch value.Signature().String() {
318+
case "y":
319+
sec = uint64(vi.(byte)) * M
320+
case "n":
321+
sec = uint64(vi.(int16)) * M
322+
case "q":
323+
sec = uint64(vi.(uint16)) * M
324+
case "i":
325+
sec = uint64(vi.(int32)) * M
326+
case "u":
327+
sec = uint64(vi.(uint32)) * M
328+
case "x":
329+
sec = uint64(vi.(int64)) * M
330+
case "t":
331+
sec = vi.(uint64) * M
332+
case "d":
333+
sec = uint64(vi.(float64) * M)
334+
default:
335+
return value, errors.New("not a number")
336+
}
337+
return dbus.MakeVariant(sec), nil
338+
}
339+
307340
func initSystemdProps(spec *specs.Spec) ([]systemdDbus.Property, error) {
308341
const keyPrefix = "org.systemd.property."
309342
var sp []systemdDbus.Property
@@ -320,6 +353,13 @@ func initSystemdProps(spec *specs.Spec) ([]systemdDbus.Property, error) {
320353
if err != nil {
321354
return nil, fmt.Errorf("Annotation %s=%s value parse error: %v", k, v, err)
322355
}
356+
if isSecSuffix(name) {
357+
name = strings.TrimSuffix(name, "Sec") + "USec"
358+
value, err = convertSecToUSec(value)
359+
if err != nil {
360+
return nil, fmt.Errorf("Annotation %s=%s value parse error: %v", k, v, err)
361+
}
362+
}
323363
sp = append(sp, systemdDbus.Property{Name: name, Value: value})
324364
}
325365

libcontainer/specconv/spec_linux_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,61 @@ func TestInitSystemdProps(t *testing.T) {
471471
in: inT{"org.systemd.property.TimeoutStopUSec", "uint64 123456789"},
472472
exp: expT{false, "TimeoutStopUSec", uint64(123456789)},
473473
},
474+
{
475+
desc: "convert USec to Sec (default numeric type)",
476+
in: inT{"org.systemd.property.TimeoutStopSec", "456"},
477+
exp: expT{false, "TimeoutStopUSec", uint64(456000000)},
478+
},
479+
{
480+
desc: "convert USec to Sec (byte)",
481+
in: inT{"org.systemd.property.TimeoutStopSec", "byte 234"},
482+
exp: expT{false, "TimeoutStopUSec", uint64(234000000)},
483+
},
484+
{
485+
desc: "convert USec to Sec (int16)",
486+
in: inT{"org.systemd.property.TimeoutStopSec", "int16 234"},
487+
exp: expT{false, "TimeoutStopUSec", uint64(234000000)},
488+
},
489+
{
490+
desc: "convert USec to Sec (uint16)",
491+
in: inT{"org.systemd.property.TimeoutStopSec", "uint16 234"},
492+
exp: expT{false, "TimeoutStopUSec", uint64(234000000)},
493+
},
494+
{
495+
desc: "convert USec to Sec (int32)",
496+
in: inT{"org.systemd.property.TimeoutStopSec", "int32 234"},
497+
exp: expT{false, "TimeoutStopUSec", uint64(234000000)},
498+
},
499+
{
500+
desc: "convert USec to Sec (uint32)",
501+
in: inT{"org.systemd.property.TimeoutStopSec", "uint32 234"},
502+
exp: expT{false, "TimeoutStopUSec", uint64(234000000)},
503+
},
504+
{
505+
desc: "convert USec to Sec (int64)",
506+
in: inT{"org.systemd.property.TimeoutStopSec", "int64 234"},
507+
exp: expT{false, "TimeoutStopUSec", uint64(234000000)},
508+
},
509+
{
510+
desc: "convert USec to Sec (uint64)",
511+
in: inT{"org.systemd.property.TimeoutStopSec", "uint64 234"},
512+
exp: expT{false, "TimeoutStopUSec", uint64(234000000)},
513+
},
514+
{
515+
desc: "convert USec to Sec (float)",
516+
in: inT{"org.systemd.property.TimeoutStopSec", "234.789"},
517+
exp: expT{false, "TimeoutStopUSec", uint64(234789000)},
518+
},
519+
{
520+
desc: "convert USec to Sec (bool -- invalid value)",
521+
in: inT{"org.systemd.property.TimeoutStopSec", "false"},
522+
exp: expT{true, "", ""},
523+
},
524+
{
525+
desc: "convert USec to Sec (string -- invalid value)",
526+
in: inT{"org.systemd.property.TimeoutStopSec", "'covfefe'"},
527+
exp: expT{true, "", ""},
528+
},
474529
{
475530
in: inT{"org.systemd.property.CollectMode", "'inactive-or-failed'"},
476531
exp: expT{false, "CollectMode", "inactive-or-failed"},

0 commit comments

Comments
 (0)
X Tutup