Skip to content

Commit

Permalink
Support [Slice] in manage_unit||dropin
Browse files Browse the repository at this point in the history
For example the following is now possible:

```puppet
systemd::manage_dropin { 'userlimits.conf':
  unit  => 'user-.slice',
  slice_entry => {
    MemoryMax        => '10G',
    MemoryAccounting => true,
  }
}
```

The directives for `[Slice]` are typically a subset of `[Service]`.

* https://www.freedesktop.org/software/systemd/man/latest/systemd.slice.html
* https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html
  • Loading branch information
traylenator committed Mar 4, 2024
1 parent df74218 commit 236f5e1
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 2 deletions.
71 changes: 71 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
* [`Systemd::Unit::Path`](#Systemd--Unit--Path): Possible keys for the [Path] section of a unit file
* [`Systemd::Unit::Service`](#Systemd--Unit--Service): Possible keys for the [Service] section of a unit file
* [`Systemd::Unit::Service::Exec`](#Systemd--Unit--Service--Exec): Possible strings for ExecStart, ExecStartPrep, ...
* [`Systemd::Unit::Slice`](#Systemd--Unit--Slice): Possible keys for the [Slice] section of a unit file
* [`Systemd::Unit::Socket`](#Systemd--Unit--Socket): Possible keys for the [Socket] section of a unit file
* [`Systemd::Unit::Timer`](#Systemd--Unit--Timer): Possible keys for the [Timer] section of a unit file
* [`Systemd::Unit::Unit`](#Systemd--Unit--Unit): Possible keys for the [Unit] section of a unit file
Expand Down Expand Up @@ -849,6 +850,18 @@ systemd::manage_dropin { 'user-aklog.conf':
}
```

##### set memory limits on the user slices

```puppet
systemd::manage_dropin { 'userlimits.conf':
unit => 'user-.slice',
slice_entry => {
MemoryMax => '10G',
MemoryAccounting => true,
}
}
```

#### Parameters

The following parameters are available in the `systemd::manage_dropin` defined type:
Expand All @@ -865,6 +878,7 @@ The following parameters are available in the `systemd::manage_dropin` defined t
* [`notify_service`](#-systemd--manage_dropin--notify_service)
* [`daemon_reload`](#-systemd--manage_dropin--daemon_reload)
* [`unit_entry`](#-systemd--manage_dropin--unit_entry)
* [`slice_entry`](#-systemd--manage_dropin--slice_entry)
* [`service_entry`](#-systemd--manage_dropin--service_entry)
* [`install_entry`](#-systemd--manage_dropin--install_entry)
* [`timer_entry`](#-systemd--manage_dropin--timer_entry)
Expand Down Expand Up @@ -965,6 +979,14 @@ key value pairs for [Unit] section of the unit file

Default value: `undef`

##### <a name="-systemd--manage_dropin--slice_entry"></a>`slice_entry`

Data type: `Optional[Systemd::Unit::Slice]`

key value pairs for [Slice] section of the unit file

Default value: `undef`

##### <a name="-systemd--manage_dropin--service_entry"></a>`service_entry`

Data type: `Optional[Systemd::Unit::Service]`
Expand Down Expand Up @@ -1108,6 +1130,7 @@ The following parameters are available in the `systemd::manage_unit` defined typ
* [`service_parameters`](#-systemd--manage_unit--service_parameters)
* [`daemon_reload`](#-systemd--manage_unit--daemon_reload)
* [`unit_entry`](#-systemd--manage_unit--unit_entry)
* [`slice_entry`](#-systemd--manage_unit--slice_entry)
* [`service_entry`](#-systemd--manage_unit--service_entry)
* [`install_entry`](#-systemd--manage_unit--install_entry)
* [`timer_entry`](#-systemd--manage_unit--timer_entry)
Expand Down Expand Up @@ -1224,6 +1247,14 @@ key value pairs for [Unit] section of the unit file.

Default value: `undef`

##### <a name="-systemd--manage_unit--slice_entry"></a>`slice_entry`

Data type: `Optional[Systemd::Unit::Slice]`

key value pairs for [Slice] section of the unit file

Default value: `undef`

##### <a name="-systemd--manage_unit--service_entry"></a>`service_entry`

Data type: `Optional[Systemd::Unit::Service]`
Expand Down Expand Up @@ -2495,6 +2526,46 @@ Possible strings for ExecStart, ExecStartPrep, ...

Alias of `Variant[Enum[''], Pattern[/^[@\-:]*(\+|!|!!)?[@\-:]*\/.*/], Pattern[/^[@\-:]*(\+|!|!!)?[@\-:]*[^\/]*(\s.*)?$/]]`

### <a name="Systemd--Unit--Slice"></a>`Systemd::Unit::Slice`

Possible keys for the [Slice] section of a unit file

* **See also**
* https://www.freedesktop.org/software/systemd/man/systemd.slice.html
* https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html

Alias of

```puppet
Struct[{
Optional['CPUAccounting'] => Boolean,
Optional['CPUQuota'] => Pattern['^([1-9][0-9]*)%$'],
Optional['CPUShares'] => Integer[2,262144],
Optional['Delegate'] => Boolean,
Optional['DeviceAllow'] => String[1],
Optional['DevicePolicy'] => Enum['auto','closed','strict'],
Optional['IOAccounting'] => Boolean,
Optional['IODeviceWeight'] => Array[Hash[Stdlib::Absolutepath, Integer[1,10000], 1, 1]],
Optional['IOReadBandwidthMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]],
Optional['IOReadIOPSMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]],
Optional['IOWeight'] => Integer[1,10000],
Optional['IOWriteBandwidthMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]],
Optional['IOWriteIOPSMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]],
Optional['MemoryAccounting'] => Boolean,
Optional['MemoryHigh'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['MemoryLimit'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'], # dep'd in systemd
Optional['MemoryLow'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['MemoryMax'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['MemoryMin'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['MemorySwapMax'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['Slice'] => String[1],
Optional['StartupCPUShares'] => Integer[2,262144],
Optional['StartupIOWeight'] => Integer[1,10000],
Optional['TasksAccounting'] => Boolean,
Optional['TasksMax'] => Variant[Integer[1],Pattern['^(infinity|([1-9][0-9]?$|^100)%)$']],
}]
```

### <a name="Systemd--Unit--Socket"></a>`Systemd::Unit::Socket`

Possible keys for the [Socket] section of a unit file
Expand Down
16 changes: 16 additions & 0 deletions manifests/manage_dropin.pp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@
# }
# }
#
# @example set memory limits on the user slices
# systemd::manage_dropin { 'userlimits.conf':
# unit => 'user-.slice',
# slice_entry => {
# MemoryMax => '10G',
# MemoryAccounting => true,
# }
# }
#
# @param unit The unit to create a dropfile for
# @param filename The target unit file to create. The filename of the drop in. The full path is determined using the path, unit and this filename.
# @param ensure The state of this dropin file
Expand All @@ -62,6 +71,7 @@
# @param notify_service Notify a service for the unit, if it exists
# @param daemon_reload Call systemd::daemon_reload
# @param unit_entry key value pairs for [Unit] section of the unit file
# @param slice_entry key value pairs for [Slice] section of the unit file
# @param service_entry key value pairs for [Service] section of the unit file
# @param install_entry key value pairs for [Install] section of the unit file
# @param timer_entry key value pairs for [Timer] section of the unit file
Expand All @@ -82,6 +92,7 @@
Boolean $daemon_reload = true,
Optional[Systemd::Unit::Install] $install_entry = undef,
Optional[Systemd::Unit::Unit] $unit_entry = undef,
Optional[Systemd::Unit::Slice] $slice_entry = undef,
Optional[Systemd::Unit::Service] $service_entry = undef,
Optional[Systemd::Unit::Timer] $timer_entry = undef,
Optional[Systemd::Unit::Path] $path_entry = undef,
Expand All @@ -99,6 +110,10 @@
fail("Systemd::Manage_dropin[${name}]: for unit ${unit} socket_entry is only valid for socket units")
}

if $slice_entry and $unit !~ Pattern['^[^/]+\.slice'] {
fail("Systemd::Manage_dropin[${name}]: for unit ${unit} slice_entry is only valid for slice units")
}

systemd::dropin_file { $name:
ensure => $ensure,
filename => $filename,
Expand All @@ -113,6 +128,7 @@
daemon_reload => $daemon_reload,
content => epp('systemd/unit_file.epp', {
'unit_entry' => $unit_entry,
'slice_entry' => $slice_entry,
'service_entry' => $service_entry,
'install_entry' => $install_entry,
'timer_entry' => $timer_entry,
Expand Down
7 changes: 7 additions & 0 deletions manifests/manage_unit.pp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
# call `systemd::daemon-reload` to ensure that the modified unit file is loaded
#
# @param unit_entry key value pairs for [Unit] section of the unit file.
# @param slice_entry key value pairs for [Slice] section of the unit file
# @param service_entry key value pairs for [Service] section of the unit file.
# @param install_entry key value pairs for [Install] section of the unit file.
# @param timer_entry key value pairs for [Timer] section of the unit file
Expand All @@ -109,6 +110,7 @@
Boolean $daemon_reload = true,
Optional[Systemd::Unit::Install] $install_entry = undef,
Optional[Systemd::Unit::Unit] $unit_entry = undef,
Optional[Systemd::Unit::Slice] $slice_entry = undef,
Optional[Systemd::Unit::Service] $service_entry = undef,
Optional[Systemd::Unit::Timer] $timer_entry = undef,
Optional[Systemd::Unit::Path] $path_entry = undef,
Expand All @@ -128,6 +130,10 @@
fail("Systemd::Manage_unit[${name}]: socket_entry is only valid for socket units")
}

if $slice_entry and $name !~ Pattern['^[^/]+\.slice'] {
fail("Systemd::Manage_unit[${name}]: slice_entry is only valid for slice units")
}

if $ensure != 'absent' and $name =~ Pattern['^[^/]+\.service'] and !$service_entry {
fail("Systemd::Manage_unit[${name}]: service_entry is required for service units")
}
Expand All @@ -146,6 +152,7 @@
daemon_reload => $daemon_reload,
content => epp('systemd/unit_file.epp', {
'unit_entry' => $unit_entry,
'slice_entry' => $slice_entry,
'service_entry' => $service_entry,
'install_entry' => $install_entry,
'timer_entry' => $timer_entry,
Expand Down
36 changes: 35 additions & 1 deletion spec/defines/manage_dropin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
is_expected.to contain_systemd__dropin_file('foobar.conf').
with_content(%r{^LimitCORE=infinity$}).
with_content(%r{^DefaultDependencies=true$}).
with_content(%r{^SyslogIdentifier=simple$})
with_content(%r{^SyslogIdentifier=simple$}).
without_content(%r{^\[Slice\]$})
}
end

Expand Down Expand Up @@ -92,6 +93,18 @@

it { is_expected.to compile.and_raise_error(%r{timer_entry is only valid for timer units}) }
end

context 'with a slice entry' do
let(:params) do
super().merge(
slice_entry: {
'MemoryMax' => '100G',
}
)
end

it { is_expected.to compile.and_raise_error(%r{slice_entry is only valid for slice units}) }
end
end

context 'on a timer' do
Expand All @@ -113,6 +126,27 @@
}
end

context 'on a slice' do
let(:params) do
{
unit: 'user-.slice',
slice_entry: {
'MemoryMax' => '10G',
'MemoryAccounting' => true,
}
}
end

it { is_expected.to compile.with_all_deps }

it {
is_expected.to contain_systemd__dropin_file('foobar.conf').
with_unit('user-.slice').
with_content(%r{^MemoryMax=10G$}).
with_content(%r{^MemoryAccounting=true$})
}
end

context 'on a path unit' do
let(:params) do
{
Expand Down
35 changes: 34 additions & 1 deletion spec/defines/manage_unit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
with_content(%r{^\[Install\]$}).
with_content(%r{^Description=My great service$}).
with_content(%r{^Description=has two lines of description$}).
with_content(%r{^Type=oneshot$})
with_content(%r{^Type=oneshot$}).
without_content(%r{^\[Slice\]$})
}

context 'with no service_entry' do
Expand Down Expand Up @@ -71,6 +72,14 @@
it { is_expected.to compile.and_raise_error(%r{timer_entry is only valid for timer units}) }
end

context 'with a slice entry' do
let(:params) do
super().merge(slice_entry: { 'IOWeight' => 100 })
end

it { is_expected.to compile.and_raise_error(%r{slice_entry is only valid for slice units}) }
end

context 'with a path entry' do
let(:params) do
super().merge(path_entry: { 'PathExists' => '/etc/passwd' })
Expand Down Expand Up @@ -161,6 +170,30 @@
}
end

context 'on a slice unit' do
let(:title) { 'myslice.slice' }
let(:params) do
{
unit_entry: {
Description: 'A crazy slice',
},
slice_entry: {
'MemoryMax' => '10G',
'IOAccounting' => true,
}
}
end

it { is_expected.to compile.with_all_deps }

it {
is_expected.to contain_systemd__unit_file('myslice.slice').
with_content(%r{^\[Slice\]$}).
with_content(%r{^MemoryMax=10G$}).
with_content(%r{^IOAccounting=true$})
}
end

context 'on a path unit' do
let(:title) { 'etc-passwd.path' }

Expand Down
21 changes: 21 additions & 0 deletions spec/type_aliases/systemd_unit_slice_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'Systemd::Unit::Slice' do
it { is_expected.to allow_value({ 'MemoryAccounting' => true }) }

it {
is_expected.to allow_value(
{
'MemoryLow' => '100',
'MemoryMin' => '10%',
'MemoryHigh' => '8G',
'MemoryMax' => 'infinity',
'MemorySwapMax' => '1T',
}
)
}

it { is_expected.not_to allow_value({ 'MemoryHigh' => '1P' }) }
end
2 changes: 2 additions & 0 deletions templates/unit_file.epp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<%- |
Optional[Hash] $unit_entry,
Optional[Hash] $slice_entry,
Optional[Hash] $service_entry,
Optional[Hash] $install_entry,
Optional[Hash] $timer_entry,
Expand All @@ -13,6 +14,7 @@

$_unit_sections = [
'Unit',
'Slice',
'Service',
'Timer',
'Path',
Expand Down
33 changes: 33 additions & 0 deletions types/unit/slice.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# @summary Possible keys for the [Slice] section of a unit file
# @see https://www.freedesktop.org/software/systemd/man/systemd.slice.html
# @see https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html
#
type Systemd::Unit::Slice = Struct[
{
Optional['CPUAccounting'] => Boolean,
Optional['CPUQuota'] => Pattern['^([1-9][0-9]*)%$'],
Optional['CPUShares'] => Integer[2,262144],
Optional['Delegate'] => Boolean,
Optional['DeviceAllow'] => String[1],
Optional['DevicePolicy'] => Enum['auto','closed','strict'],
Optional['IOAccounting'] => Boolean,
Optional['IODeviceWeight'] => Array[Hash[Stdlib::Absolutepath, Integer[1,10000], 1, 1]],
Optional['IOReadBandwidthMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]],
Optional['IOReadIOPSMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]],
Optional['IOWeight'] => Integer[1,10000],
Optional['IOWriteBandwidthMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]],
Optional['IOWriteIOPSMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]],
Optional['MemoryAccounting'] => Boolean,
Optional['MemoryHigh'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['MemoryLimit'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'], # dep'd in systemd
Optional['MemoryLow'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['MemoryMax'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['MemoryMin'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['MemorySwapMax'] => Pattern['\A(infinity|\d+(K|M|G|T|%)?(:\d+(K|M|G|T|%)?)?)\z'],
Optional['Slice'] => String[1],
Optional['StartupCPUShares'] => Integer[2,262144],
Optional['StartupIOWeight'] => Integer[1,10000],
Optional['TasksAccounting'] => Boolean,
Optional['TasksMax'] => Variant[Integer[1],Pattern['^(infinity|([1-9][0-9]?$|^100)%)$']],
}
]

0 comments on commit 236f5e1

Please sign in to comment.