66 "math"
77 "os"
88 "path/filepath"
9+ "strconv"
910 "strings"
1011 "sync"
1112
@@ -14,6 +15,7 @@ import (
1415 "github.com/opencontainers/runc/libcontainer/cgroups"
1516 "github.com/opencontainers/runc/libcontainer/cgroups/fs2"
1617 "github.com/opencontainers/runc/libcontainer/configs"
18+ "github.com/pkg/errors"
1719)
1820
1921type unifiedManager struct {
@@ -89,14 +91,17 @@ func (m *unifiedManager) Apply(pid int) error {
8991 var (
9092 c = m .cgroups
9193 unitName = getUnitName (c )
92- slice = "system.slice"
9394 properties []systemdDbus.Property
9495 )
9596
9697 if c .Paths != nil {
9798 return cgroups .WriteCgroupProc (m .path , pid )
9899 }
99100
101+ slice := "system.slice"
102+ if m .rootless {
103+ slice = "user.slice"
104+ }
100105 if c .Parent != "" {
101106 slice = c .Parent
102107 }
@@ -140,9 +145,13 @@ func (m *unifiedManager) Apply(pid int) error {
140145 properties = append (properties , resourcesProperties ... )
141146 properties = append (properties , c .SystemdProps ... )
142147
143- if err := startUnit (unitName , properties ); err != nil {
148+ dbusConnection , err := getDbusConnection (m .rootless )
149+ if err != nil {
144150 return err
145151 }
152+ if err := startUnit (dbusConnection , unitName , properties ); err != nil {
153+ return errors .Wrapf (err , "error while starting unit %q with properties %+v" , unitName , properties )
154+ }
146155
147156 _ , err = m .GetUnifiedPath ()
148157 if err != nil {
@@ -161,13 +170,17 @@ func (m *unifiedManager) Destroy() error {
161170 m .mu .Lock ()
162171 defer m .mu .Unlock ()
163172
173+ dbusConnection , err := getDbusConnection (m .rootless )
174+ if err != nil {
175+ return err
176+ }
164177 unitName := getUnitName (m .cgroups )
165- if err := stopUnit (unitName ); err != nil {
178+ if err := stopUnit (dbusConnection , unitName ); err != nil {
166179 return err
167180 }
168181
169182 // XXX this is probably not needed, systemd should handle it
170- err : = os .Remove (m .path )
183+ err = os .Remove (m .path )
171184 if err != nil && ! os .IsNotExist (err ) {
172185 return err
173186 }
@@ -190,31 +203,66 @@ func (m *unifiedManager) GetPaths() map[string]string {
190203 return paths
191204}
192205
206+ // getSliceFull value is used in GetUnifiedPath.
207+ // The value is incompatible with systemdDbus.PropSlice.
208+ func (m * unifiedManager ) getSliceFull () (string , error ) {
209+ c := m .cgroups
210+ slice := "system.slice"
211+ if m .rootless {
212+ slice = "user.slice"
213+ }
214+ if c .Parent != "" {
215+ var err error
216+ slice , err = ExpandSlice (c .Parent )
217+ if err != nil {
218+ return "" , err
219+ }
220+ }
221+
222+ if m .rootless {
223+ dbusConnection , err := getDbusConnection (m .rootless )
224+ if err != nil {
225+ return "" , err
226+ }
227+ // managerCGQuoted is typically "/user.slice/user-${uid}.slice/user@${uid}.service" including the quote symbols
228+ managerCGQuoted , err := dbusConnection .GetManagerProperty ("ControlGroup" )
229+ if err != nil {
230+ return "" , err
231+ }
232+ managerCG , err := strconv .Unquote (managerCGQuoted )
233+ if err != nil {
234+ return "" , err
235+ }
236+ slice = filepath .Join (managerCG , slice )
237+ }
238+
239+ // an example of the final slice in rootless: "/user.slice/user-1001.slice/[email protected] /user.slice" 240+ // NOTE: systemdDbus.PropSlice requires the "/user.slice/user-1001.slice/[email protected] /" prefix NOT to be specified. 241+ return slice , nil
242+ }
243+
193244func (m * unifiedManager ) GetUnifiedPath () (string , error ) {
194245 m .mu .Lock ()
195246 defer m .mu .Unlock ()
196247 if m .path != "" {
197248 return m .path , nil
198249 }
199250
200- c := m .cgroups
201- slice := "system.slice"
202- if c .Parent != "" {
203- slice = c .Parent
204- }
205-
206- slice , err := ExpandSlice (slice )
251+ sliceFull , err := m .getSliceFull ()
207252 if err != nil {
208253 return "" , err
209254 }
210255
211- path := filepath .Join (slice , getUnitName (c ))
256+ c := m .cgroups
257+ path := filepath .Join (sliceFull , getUnitName (c ))
212258 path , err = securejoin .SecureJoin (fs2 .UnifiedMountpoint , path )
213259 if err != nil {
214260 return "" , err
215261 }
216262 m .path = path
217263
264+ // an example of the final path in rootless:
265+ // "/sys/fs/cgroup/user.slice/user-1001.slice/[email protected] /user.slice/libpod-132ff0d72245e6f13a3bbc6cdc5376886897b60ac59eaa8dea1df7ab959cbf1c.scope" 218266 return m .path , nil
219267}
220268
@@ -263,12 +311,12 @@ func (m *unifiedManager) Set(container *configs.Config) error {
263311 if err != nil {
264312 return err
265313 }
266- dbusConnection , err := getDbusConnection ()
314+ dbusConnection , err := getDbusConnection (m . rootless )
267315 if err != nil {
268316 return err
269317 }
270318 if err := dbusConnection .SetUnitProperties (getUnitName (m .cgroups ), true , properties ... ); err != nil {
271- return err
319+ return errors . Wrap ( err , "error while setting unit properties" )
272320 }
273321
274322 fsMgr , err := m .fsManager ()
0 commit comments