Skip to content

Commit

Permalink
feat: linux control group version 2 API support cgroup v2
Browse files Browse the repository at this point in the history
  • Loading branch information
ChangxinDong committed Oct 13, 2022
1 parent 7730b18 commit ea1823a
Show file tree
Hide file tree
Showing 10 changed files with 502 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.aws.greengrass.testcommons.testutilities.GGExtension;
import com.aws.greengrass.testcommons.testutilities.TestUtils;
import com.aws.greengrass.util.platforms.unix.linux.Cgroup;
import com.aws.greengrass.util.platforms.unix.linux.CgroupSubSystem;
import com.aws.greengrass.util.platforms.unix.linux.LinuxSystemResourceController;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -115,7 +116,7 @@ void GIVEN_LifeCycleEventStreamClient_WHEN_pause_resume_component_THEN_target_se
private LinuxSystemResourceController.CgroupFreezerState getCgroupFreezerState(String serviceName)
throws IOException {
return LinuxSystemResourceController.CgroupFreezerState.valueOf(
new String(Files.readAllBytes(Cgroup.Freezer.getCgroupFreezerStateFilePath(serviceName)),
new String(Files.readAllBytes(new Cgroup(CgroupSubSystem.Freezer).getCgroupFreezerStateFilePath(serviceName)),
StandardCharsets.UTF_8).trim());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.aws.greengrass.testcommons.testutilities.NoOpPathOwnershipHandler;
import com.aws.greengrass.util.Pair;
import com.aws.greengrass.util.platforms.unix.linux.Cgroup;
import com.aws.greengrass.util.platforms.unix.linux.CgroupSubSystem;
import com.aws.greengrass.util.platforms.unix.linux.LinuxSystemResourceController;
import org.apache.commons.lang3.SystemUtils;
import org.junit.jupiter.api.AfterEach;
Expand Down Expand Up @@ -713,11 +714,11 @@ void GIVEN_service_starts_up_WHEN_startup_times_out_THEN_timeout_error_code_pers
}

private void assertResourceLimits(String componentName, long memory, double cpus) throws Exception {
byte[] buf1 = Files.readAllBytes(Cgroup.Memory.getComponentMemoryLimitPath(componentName));
byte[] buf1 = Files.readAllBytes(new Cgroup(CgroupSubSystem.Memory).getComponentMemoryLimitPath(componentName));
assertThat(memory, equalTo(Long.parseLong(new String(buf1, StandardCharsets.UTF_8).trim())));

byte[] buf2 = Files.readAllBytes(Cgroup.CPU.getComponentCpuQuotaPath(componentName));
byte[] buf3 = Files.readAllBytes(Cgroup.CPU.getComponentCpuPeriodPath(componentName));
byte[] buf2 = Files.readAllBytes(new Cgroup(CgroupSubSystem.CPU).getComponentCpuQuotaPath(componentName));
byte[] buf3 = Files.readAllBytes(new Cgroup(CgroupSubSystem.CPU).getComponentCpuPeriodPath(componentName));

int quota = Integer.parseInt(new String(buf2, StandardCharsets.UTF_8).trim());
int period = Integer.parseInt(new String(buf3, StandardCharsets.UTF_8).trim());
Expand Down Expand Up @@ -761,7 +762,7 @@ void GIVEN_running_service_WHEN_pause_resume_requested_THEN_pause_resume_Service
private LinuxSystemResourceController.CgroupFreezerState getCgroupFreezerState(String serviceName)
throws IOException {
return LinuxSystemResourceController.CgroupFreezerState
.valueOf(new String(Files.readAllBytes(Cgroup.Freezer.getCgroupFreezerStateFilePath(serviceName))
.valueOf(new String(Files.readAllBytes(new Cgroup(CgroupSubSystem.Freezer).getCgroupFreezerStateFilePath(serviceName))
, StandardCharsets.UTF_8).trim());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,62 @@
package com.aws.greengrass.util.platforms.unix.linux;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.lang3.StringUtils;

import java.nio.file.Path;
import java.nio.file.Paths;

/**
* Represents Linux cgroup v1 subsystems.
* Represents Linux cgroup subsystems.
*/
@SuppressFBWarnings(value = "DMI_HARDCODED_ABSOLUTE_FILENAME", justification = "Cgroup virtual filesystem path "
+ "cannot be relative")
public enum Cgroup {
Memory("memory"), CPU("cpu,cpuacct"), Freezer("freezer", "freezer");

public class Cgroup {
private static final String CGROUP_ROOT = "/sys/fs/cgroup";
private static final String GG_NAMESPACE = "greengrass";
private static final String CGROUP_MEMORY_LIMITS = "memory.limit_in_bytes";
private static final String CPU_CFS_PERIOD_US = "cpu.cfs_period_us";
private static final String CPU_CFS_QUOTA_US = "cpu.cfs_quota_us";
private static final String CGROUP_PROCS = "cgroup.procs";
private static final String FREEZER_STATE_FILE = "freezer.state";
private static final String CPU_MAX = "cpu.max";
private static final String MEMORY_MAX = "memory.max";
private static final String CGROUP_SUBTREE_CONTROL = "cgroup.subtree_control";
private static final String CGROUP_FREEZE = "cgroup.freeze";

private final String osString;
private final String mountSrc;

Cgroup(String str) {
osString = str;
mountSrc = "cgroup";
/**
* Cgroup constructor.
*
* @param subSystem subController
*/
public Cgroup(CgroupSubSystem subSystem) {
this.osString = subSystem.getOsString();
this.mountSrc = subSystem.getMountSrc();
}

Cgroup(String str, String mountSrc) {
this.osString = str;
this.mountSrc = mountSrc;
Cgroup(CgroupSubSystemV2 subSystemV2) {
this.osString = subSystemV2.getOsString();
this.mountSrc = subSystemV2.getMountSrc();
}

public static Path getRootPath() {
return Paths.get(CGROUP_ROOT);
}

public static String rootMountCmd() {
return String.format("mount -t tmpfs cgroup %s", CGROUP_ROOT);
/**
* root mount cmd.
*
* @return mount command string
*/
public String rootMountCmd() {
if (StringUtils.isEmpty(osString)) {
return String.format("mount -t cgroup2 none %s", CGROUP_ROOT);
} else {
return String.format("mount -t tmpfs cgroup %s", CGROUP_ROOT);
}
}

public String subsystemMountCmd() {
Expand All @@ -63,8 +80,18 @@ public Path getSubsystemComponentPath(String componentName) {
return getSubsystemGGPath().resolve(componentName);
}

/**
* get component memory limit path.
*
* @param componentName componentName
* @return memory limit Path
*/
public Path getComponentMemoryLimitPath(String componentName) {
return getSubsystemComponentPath(componentName).resolve(CGROUP_MEMORY_LIMITS);
if (StringUtils.isEmpty(osString)) {
return getSubsystemComponentPath(componentName).resolve(MEMORY_MAX);
} else {
return getSubsystemComponentPath(componentName).resolve(CGROUP_MEMORY_LIMITS);
}
}

public Path getComponentCpuPeriodPath(String componentName) {
Expand All @@ -79,7 +106,34 @@ public Path getCgroupProcsPath(String componentName) {
return getSubsystemComponentPath(componentName).resolve(CGROUP_PROCS);
}

/**
* get cgroup freezer path.
*
* @param componentName componentName
* @return cgroup freezer path
*/
public Path getCgroupFreezerStateFilePath(String componentName) {
return getSubsystemComponentPath(componentName).resolve(FREEZER_STATE_FILE);
if (StringUtils.isEmpty(osString)) {
return getSubsystemComponentPath(componentName).resolve(CGROUP_FREEZE);
} else {
return getSubsystemComponentPath(componentName).resolve(FREEZER_STATE_FILE);
}
}

public Path getRootSubTreeControlPath() {
return getSubsystemRootPath().resolve(CGROUP_SUBTREE_CONTROL);
}

public Path getGGSubTreeControlPath() {
return getSubsystemGGPath().resolve(CGROUP_SUBTREE_CONTROL);
}

public Path getComponentCpuMaxPath(String componentName) {
return getSubsystemComponentPath(componentName).resolve(CPU_MAX);
}

public Path getCgroupFreezePath(String componentName) {
return getSubsystemComponentPath(componentName).resolve(CGROUP_FREEZE);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package com.aws.greengrass.util.platforms.unix.linux;

public enum CgroupSubSystem {
Memory("memory", ""), CPU("cpu,cpuacct", ""), Freezer("freezer", "freezer");

private String osString;
private String mountSrc;

CgroupSubSystem(String osString, String mountSrc) {
this.osString = osString;
this.mountSrc = mountSrc;
}

/**
* Get the osString associated with this CgroupSubController.
*
* @return the osString associated with this CgroupSubController.
*/
public String getOsString() {
return osString;
}

/**
* Get the mountSrc associated with this CgroupSubController.
*
* @return the mountSrc associated with this CgroupSubController.
*/
public String getMountSrc() {
return mountSrc;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package com.aws.greengrass.util.platforms.unix.linux;

public enum CgroupSubSystemV2 {
Memory("", ""), CPU("", ""), Freezer("", ""),
Unified("","");

private String osString;
private String mountSrc;

CgroupSubSystemV2(String osString, String mountSrc) {
this.osString = osString;
this.mountSrc = mountSrc;
}

/**
* Get the osString associated with this CgroupSubController.
*
* @return the osString associated with this CgroupSubController.
*/
public String getOsString() {
return osString;
}

/**
* Get the mountSrc associated with this CgroupSubController.
*
* @return the mountSrc associated with this CgroupSubController.
*/
public String getMountSrc() {
return mountSrc;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package com.aws.greengrass.util.platforms.unix.linux;

public enum CgroupV2FreezerState {
THAWED(0),
FROZEN(1);

private int index;

CgroupV2FreezerState(int index) {
this.index = index;
}

/**
* Get the index value associated with this CgroupV2FreezerState.
*
* @return the integer index value associated with this CgroupV2FreezerState.
*/
public int getIndex() {
return index;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,33 @@

import com.aws.greengrass.util.platforms.SystemResourceController;
import com.aws.greengrass.util.platforms.unix.UnixPlatform;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@SuppressFBWarnings(value = "DMI_HARDCODED_ABSOLUTE_FILENAME",
justification = "Cgroup Controller virtual filesystem path cannot be relative")
public class LinuxPlatform extends UnixPlatform {
SystemResourceController systemResourceController = new LinuxSystemResourceController(this);
private static final String CGROUP_ROOT = "/sys/fs/cgroup";
private static final String CGROUP_CONTROLLERS = "cgroup.controllers";

SystemResourceController systemResourceController;

@Override
public SystemResourceController getSystemResourceController() {
//if the path exists, identify it as cgroupv1, otherwise identify it as cgroupv2
if (Files.exists(getControllersRootPath())) {
systemResourceController = new LinuxSystemResourceControllerV2(this);
} else {
systemResourceController = new LinuxSystemResourceController(this);
}

return systemResourceController;
}

private Path getControllersRootPath() {
return Paths.get(CGROUP_ROOT).resolve(CGROUP_CONTROLLERS);
}
}
Loading

0 comments on commit ea1823a

Please sign in to comment.