cosmetic - slightly changed message when a freezer cgroup file can't be figured out
[nodemanager.git] / cgroups.py
1 # Simple wrapper arround cgroups so we don't have to worry the type of
2 # virtualization the sliver runs on (lxc, qemu/kvm, etc.) managed by libvirt
3 #
4 # Xavi Leon <xleon@ac.upc.edu>
5
6 import os
7 import pyinotify
8 import logger
9
10 # Base dir for libvirt
11 BASE_DIR = '/sys/fs/cgroup'
12 SUB_SYSTEMS = ['blkio', 'freezer', 'devices', 'memory', 'cpu,cpuacct', 'cpuset']
13 VIRT_TECHS = ['lxc']
14
15 # Global cgroup mapping. 
16 CGROUPS = dict()
17
18 class CgroupWatch(pyinotify.ProcessEvent):
19
20     def process_IN_CREATE(self, event):
21         path = os.path.join(event.path, event.name)
22         CGROUPS[event.name] = path
23         logger.verbose("Cgroup Notify: Created cgroup %s on %s" % \
24                         (event.name, event.path))
25         
26     def process_IN_DELETE(self, event):
27         try:
28             del CGROUPS[event.name]
29         except:
30             logger.verbose("Cgroup Notify: Cgroup %s does not exist, continuing..."%event.name)
31         logger.verbose("Cgroup Notify: Deleted cgroup %s on %s" % \
32                         (event.name, event.path))
33
34
35 #logger.verbose("Cgroups: Recognizing already existing cgroups...")
36 #for virt in VIRT_TECHS:
37 #    filenames = os.listdir(os.path.join(BASE_DIR, virt))
38 #    for filename in filenames:
39 #        path = os.path.join(BASE_DIR, virt, filename)
40 #        if os.path.isdir(path):
41 #            CGROUPS[filename] = path
42
43 #logger.verbose("Cgroups: Initializing watchers...")
44 #wm = pyinotify.WatchManager()
45 #notifier = pyinotify.ThreadedNotifier(wm, CgroupWatch())
46 #for virt in VIRT_TECHS:
47 #    wdd = wm.add_watch(os.path.join(BASE_DIR, virt),
48 #               pyinotify.IN_DELETE | pyinotify.IN_CREATE,
49 #               rec=False)
50 #notifier.daemon = True
51 #notifier.start()
52
53 def get_cgroup_paths(subsystem="cpuset"):
54     subsystem_bases = [ 
55         # observed on f16-f18
56         os.path.join(BASE_DIR, subsystem, 'libvirt', 'lxc'),
57         # as observed on f20
58         os.path.join(BASE_DIR, subsystem ),
59         # f21
60         os.path.join(BASE_DIR, subsystem, 'machine.slice'),
61         # as observed on f16 libvirt 1.2.1
62         os.path.join(BASE_DIR, subsystem, 'machine'),
63         ]
64     # try several locations and return all the results
65     # get_cgroup_path will sort it out
66     
67     # just return all the subdirs in the listed bases 
68     return [ subdir
69                  # scan the bases
70                  for subsystem_base in subsystem_bases if os.path.isdir(subsystem_base)
71                      # in each base search the immediate sons that are also dirs
72                      for subdir in [ os.path.join(subsystem_base, f) for f in os.listdir(subsystem_base) ]
73                          if os.path.isdir(subdir) ]
74
75 def get_cgroup_path(name, subsystem="cpuset"):
76     """
77     Returns the base path for the cgroup with a specific name or None.
78     """
79     result = reduce(lambda a, b: b if name in os.path.basename(b) else a,
80                     get_cgroup_paths(subsystem), None)
81
82     if result is None:
83         name = name + ".libvirt-lxc"
84         result = reduce(lambda a, b: b if name in os.path.basename(b) else a,
85                         get_cgroup_paths(subsystem), None)
86
87     return result
88
89 def get_base_path():
90     return BASE_DIR
91
92 def get_cgroups():
93     """ Returns the list of cgroups active at this moment on the node """
94     return map(os.path.basename, get_cgroup_paths())
95
96 def write(name, key, value, subsystem="cpuset"):
97     """ Writes a value to the file key with the cgroup with name """
98     base_path = get_cgroup_path(name, subsystem)
99     with open(os.path.join(base_path, key), 'w') as f:
100         print >>f, value
101
102 def append(name, key, value, subsystem="cpuset"):
103     """ Appends a value to the file key with the cgroup with name """
104     base_path = get_cgroup_path(name, subsystem)
105     with open(os.path.join(base_path, key), 'a') as f:
106         print >>f, value
107
108 if __name__ == '__main__':
109
110     # goes with the system tests
111     name='inri_sl1' 
112
113     subsystems = 'blkio cpu cpu,cpuacct cpuacct cpuset devices freezer memory net_cls perf_event systemd'.split()
114
115     for subsystem in subsystems:
116         print 'get_cgroup_path({}, {}) =  {}'.\
117             format(name, subsystem, get_cgroup_path(name, subsystem))
118
119 #        print 'get_cgroup_paths = {}'.format(get_cgroup_paths(subsystem))