#!/usr/bin/python1###############################################################################2#3# CoCalc: Collaborative Calculation in the Cloud4#5# Copyright (C) 2016, Sagemath Inc.6#7# This program is free software: you can redistribute it and/or modify8# it under the terms of the GNU General Public License as published by9# the Free Software Foundation, either version 3 of the License, or10# (at your option) any later version.11#12# This program is distributed in the hope that it will be useful,13# but WITHOUT ANY WARRANTY; without even the implied warranty of14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15# GNU General Public License for more details.16#17# You should have received a copy of the GNU General Public License18# along with this program. If not, see <http://www.gnu.org/licenses/>.19#20###############################################################################21222324import os, sys25from subprocess import Popen, PIPE2627progname, username, memory_G, cpu_shares, cfs_quota = sys.argv2829if not os.path.exists('/sys/fs/cgroup/memory'):30raise RuntimeError("cgroups not supported")3132def cmd(s, ignore_errors=False):33print s34out = Popen(s, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)35x = out.stdout.read() + out.stderr.read()36e = out.wait() # this must be *after* the out.stdout.read(), etc. above or will hang when output large!37if e:38if ignore_errors:39return (x + "ERROR").strip()40else:41raise RuntimeError(x)42return x.strip()4344cmd("cgcreate -g memory,cpu:%s"%username)45open("/sys/fs/cgroup/memory/%s/memory.limit_in_bytes"%username,'w').write("%sG"%memory_G)46open("/sys/fs/cgroup/cpu/%s/cpu.shares"%username,'w').write(cpu_shares)47open("/sys/fs/cgroup/cpu/%s/cpu.cfs_quota_us"%username,'w').write(cfs_quota)4849z = "\n%s cpu,memory %s\n"%(username, username)50cur = open("/etc/cgrules.conf").read()5152if z not in cur:53open("/etc/cgrules.conf",'a').write(z)54cmd('service cgred restart')5556try:57pids = cmd("ps -o pid -u %s"%username, ignore_errors=False).split()[1:]58except RuntimeError:59# ps returns an error code if there are NO processes at all (a common condition).60pids = []61if pids:62cmd("cgclassify %s"%(' '.join(pids)), ignore_errors=True)63# ignore cgclassify errors, since processes come and go, etc.6465666768