blob: 67c0482dd5b99fee0b3db9d9fd63a05dd5a093f4 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version
* 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package org.apache.storm.container.cgroup;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.storm.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CgroupCenter implements CgroupOperation {
private static Logger LOG = LoggerFactory.getLogger(CgroupCenter.class);
private static CgroupCenter instance;
private CgroupCenter() {
}
public static synchronized CgroupCenter getInstance() {
if (CgroupUtils.enabled()) {
instance = new CgroupCenter();
return instance;
}
return null;
}
@Override
public List<Hierarchy> getHierarchies() {
Map<String, Hierarchy> hierarchies = new HashMap<String, Hierarchy>();
try (FileReader reader = new FileReader(CgroupUtils.MOUNT_STATUS_FILE);
BufferedReader br = new BufferedReader(reader)) {
String str = null;
while ((str = br.readLine()) != null) {
String[] strSplit = str.split(" ");
if (!strSplit[2].equals("cgroup")) {
continue;
}
String name = strSplit[0];
String type = strSplit[3];
String dir = strSplit[1];
//Some mount options (i.e. rw and relatime) in type are not cgroups related
Hierarchy h = new Hierarchy(name, CgroupUtils.getSubSystemsFromString(type), dir);
hierarchies.put(type, h);
}
return new ArrayList<Hierarchy>(hierarchies.values());
} catch (Exception e) {
LOG.error("Get hierarchies error {}", e);
}
return null;
}
@Override
public Set<SubSystem> getSubSystems() {
Set<SubSystem> subSystems = new HashSet<SubSystem>();
try (FileReader reader = new FileReader(CgroupUtils.CGROUP_STATUS_FILE);
BufferedReader br = new BufferedReader(reader)) {
String str = null;
while ((str = br.readLine()) != null) {
String[] split = str.split("\t");
SubSystemType type = SubSystemType.getSubSystem(split[0]);
if (type == null) {
continue;
}
int hierarchyId = Integer.valueOf(split[1]);
int cgroupNum = Integer.valueOf(split[2]);
boolean enable = Integer.valueOf(split[3]).intValue() == 1 ? true : false;
subSystems.add(new SubSystem(type, hierarchyId, cgroupNum, enable));
}
return subSystems;
} catch (Exception e) {
LOG.error("Get subSystems error {}", e);
}
return null;
}
@Override
public boolean isSubSystemEnabled(SubSystemType subSystemType) {
Set<SubSystem> subSystems = this.getSubSystems();
for (SubSystem subSystem : subSystems) {
if (subSystem.getType() == subSystemType) {
return true;
}
}
return false;
}
@Override
public Hierarchy getHierarchyWithSubSystem(SubSystemType subSystem) {
return getHierarchyWithSubSystems(Arrays.asList(subSystem));
}
@Override
public Hierarchy getHierarchyWithSubSystems(List<SubSystemType> subSystems) {
List<Hierarchy> hierarchies = this.getHierarchies();
for (Hierarchy hierarchy : hierarchies) {
Hierarchy ret = hierarchy;
for (SubSystemType subSystem : subSystems) {
if (!hierarchy.getSubSystems().contains(subSystem)) {
ret = null;
break;
}
}
if (ret != null) {
return ret;
}
}
return null;
}
@Override
public boolean isMounted(Hierarchy hierarchy) {
if (Utils.checkDirExists(hierarchy.getDir())) {
List<Hierarchy> hierarchies = this.getHierarchies();
for (Hierarchy h : hierarchies) {
if (h.equals(hierarchy)) {
return true;
}
}
}
return false;
}
@Override
public void mount(Hierarchy hierarchy) throws IOException {
if (this.isMounted(hierarchy)) {
LOG.error("{} is already mounted", hierarchy.getDir());
return;
}
Set<SubSystemType> subSystems = hierarchy.getSubSystems();
for (SubSystemType type : subSystems) {
Hierarchy hierarchyWithSubSystem = this.getHierarchyWithSubSystem(type);
if (hierarchyWithSubSystem != null) {
LOG.error("subSystem: {} is already mounted on hierarchy: {}", type.name(), hierarchyWithSubSystem);
subSystems.remove(type);
}
}
if (subSystems.size() == 0) {
return;
}
if (!Utils.checkDirExists(hierarchy.getDir())) {
new File(hierarchy.getDir()).mkdirs();
}
String subSystemsName = CgroupUtils.subSystemsToString(subSystems);
SystemOperation.mount(subSystemsName, hierarchy.getDir(), "cgroup", subSystemsName);
}
@Override
public void umount(Hierarchy hierarchy) throws IOException {
if (this.isMounted(hierarchy)) {
hierarchy.getRootCgroups().delete();
SystemOperation.umount(hierarchy.getDir());
CgroupUtils.deleteDir(hierarchy.getDir());
} else {
LOG.error("{} is not mounted", hierarchy.getDir());
}
}
@Override
public void createCgroup(CgroupCommon cgroup) throws SecurityException {
if (cgroup.isRoot()) {
LOG.error("You can't create rootCgroup in this function");
throw new RuntimeException("You can't create rootCgroup in this function");
}
CgroupCommon parent = cgroup.getParent();
while (parent != null) {
if (!Utils.checkDirExists(parent.getDir())) {
throw new RuntimeException("Parent " + parent.getDir() + "does not exist");
}
parent = parent.getParent();
}
Hierarchy h = cgroup.getHierarchy();
if (!isMounted(h)) {
throw new RuntimeException("hierarchy " + h.getDir() + " is not mounted");
}
if (Utils.checkDirExists(cgroup.getDir())) {
throw new RuntimeException("cgroup {} already exists " + cgroup.getDir());
}
if (!(new File(cgroup.getDir())).mkdir()) {
throw new RuntimeException("Could not create cgroup dir at " + cgroup.getDir());
}
}
@Override
public void deleteCgroup(CgroupCommon cgroup) throws IOException {
cgroup.delete();
}
}