1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-only
#
# Test to create a systemd scope using cgcreate
#
# Copyright (c) 2023 Oracle and/or its affiliates.
# Author: Tom Hromatka <tom.hromatka@oracle.com>
#
from process import Process
from systemd import Systemd
from libcgroup import Mode
from cgroup import Cgroup
from run import RunError
from log import Log
import consts
import ftests
import sys
import os
CONTROLLERS = ['cpu', 'pids']
SLICE = 'libcgroup.slice'
CGNAME = os.path.join(SLICE, '078cgcreate.scope')
IN_SCOPE_CHILD_CGNAME = os.path.join(CGNAME, 'in_scope_childcg')
OUT_OF_SCOPE_CHILD_CGNAME = '078outofscopechild'
INVAL_CGNAME = os.path.join(SLICE, 'cpu.scope')
def prereqs(config):
result = consts.TEST_PASSED
cause = None
if config.args.container:
result = consts.TEST_SKIPPED
cause = 'This test cannot be run within a container'
return result, cause
if Cgroup.get_cgroup_mode(config) != Mode.CGROUP_MODE_UNIFIED:
result = consts.TEST_SKIPPED
cause = 'This test requires the unified cgroup hierarchy'
if not Systemd.is_systemd_enabled():
result = consts.TEST_SKIPPED
cause = 'Systemd support not compiled in'
return result, cause
def setup(config):
pass
def test(config):
result = consts.TEST_PASSED
cause = None
Cgroup.create_and_validate(config, CONTROLLERS, CGNAME, create_scope=True)
# get the placeholder PID that libcgroup placed in the scope
try:
pid = int(Cgroup.get(config, None, CGNAME, setting='cgroup.procs',
print_headers=False, values_only=True, ignore_systemd=True))
# use the pid variable so that lint is happy
Log.log_debug('Cgroup {} has pid {}'.format(CGNAME, pid))
except RunError:
result = consts.TEST_FAILED
cause = "Failed to read pid in {}'s cgroup.procs".format(CGNAME)
return result, cause
# Since the scope was created without being made the default, we must specify
# the entire path to operate on a child cgroup below the scope.
Cgroup.create_and_validate(config, None, IN_SCOPE_CHILD_CGNAME)
Cgroup.create_and_validate(config, None, OUT_OF_SCOPE_CHILD_CGNAME)
try:
Cgroup.create_and_validate(config, CONTROLLERS, INVAL_CGNAME, create_scope=True)
except RunError as re:
if 'Invalid scope name, using controller name cpu' not in str(re):
raise re
else:
result = consts.TEST_FAILED
cause = 'Erroneously succeeded in creating scope {}', format(INVAL_CGNAME)
return result, cause
def teardown(config):
Cgroup.delete(config, None, IN_SCOPE_CHILD_CGNAME)
Cgroup.delete(config, None, OUT_OF_SCOPE_CHILD_CGNAME)
pid = int(Cgroup.get(config, None, CGNAME, setting='cgroup.procs',
print_headers=False, values_only=True, ignore_systemd=True))
Process.kill(config, pid)
# try deleting INVAL_CGNAME for the cases, where it was erroneously created.
try:
pid = int(Cgroup.get(config, None, INVAL_CGNAME, setting='cgroup.procs',
print_headers=False, values_only=True, ignore_systemd=True))
Process.kill(config, pid)
except RunError:
pass
# systemd will automatically remove the cgroup once there are no more pids in
# the cgroup, so we don't need to delete CGNAME. But let's try to remove the
# slice
try:
Cgroup.delete(config, CONTROLLERS, SLICE)
except RunError:
pass
def main(config):
[result, cause] = prereqs(config)
if result != consts.TEST_PASSED:
return [result, cause]
setup(config)
[result, cause] = test(config)
teardown(config)
return [result, cause]
if __name__ == '__main__':
config = ftests.parse_args()
# this test was invoked directly. run only it
config.args.num = int(os.path.basename(__file__).split('-')[0])
sys.exit(ftests.main(config))
# vim: set et ts=4 sw=4:
|