cgroups

PROD-16845

Change-Id: Iabc6f4584e34c988e67ff42ee8ceb20c469823d6
diff --git a/README.rst b/README.rst
index 1184d0a..930557b 100644
--- a/README.rst
+++ b/README.rst
@@ -421,6 +421,51 @@
           governor: performance
 
 
+CGROUPS
+~~~~~~~
+
+Setup linux cgroups:
+
+.. code-block:: yaml
+
+    linux:
+      system:
+        cgroup:
+          enabled: true
+          group:
+            ceph_group_1:
+              controller:
+                cpu:
+                  shares:
+                    value: 250
+                cpuacct:
+                  usage:
+                    value: 0
+                cpuset:
+                  cpus:
+                    value: 1,2,3
+                memory:
+                  limit_in_bytes:
+                    value: 2G
+                  memsw.limit_in_bytes:
+                    value: 3G
+              mapping:
+                subjects:
+                - '@ceph'
+            generic_group_1:
+              controller:
+                cpu:
+                  shares:
+                    value: 250
+                cpuacct:
+                  usage:
+                    value: 0
+              mapping:
+                subjects:
+                - '*:firefox'
+                - 'student:cp'
+
+
 Shared Libraries
 ~~~~~~~~~~~~~~~~
 
diff --git a/linux/files/cgconfig.conf b/linux/files/cgconfig.conf
new file mode 100644
index 0000000..0ea2e75
--- /dev/null
+++ b/linux/files/cgconfig.conf
@@ -0,0 +1,16 @@
+{%- from "linux/map.jinja" import system with context -%}
+##
+## This is cgconfig configuration file is managed by Salt
+##
+{%- for cgroup_name, cg in system.cgroup.group.iteritems() %}
+group {{ cgroup_name }} {
+  {%- for controller_name, controller in cg.controller.iteritems() %}
+        {{ controller_name }} {
+    {%- for v_name, v in controller.iteritems() %}
+                {{ controller_name }}.{{ v_name }}="{{ v.value }}";
+    {%- endfor %}
+
+        }
+  {%- endfor %}
+}
+{%- endfor %}
diff --git a/linux/files/cgrules.conf b/linux/files/cgrules.conf
new file mode 100644
index 0000000..116a9d6
--- /dev/null
+++ b/linux/files/cgrules.conf
@@ -0,0 +1,10 @@
+{%- from "linux/map.jinja" import system with context -%}
+##
+## This is cgrules configuration file is managed by Salt
+##
+#<user/group>         <controller(s)>         <cgroup>
+{%- for cgroup_name, cg in system.cgroup.group.iteritems() %}
+{%- for subject in cg.mapping.subjects %}
+{{ subject }}{% raw %}         {% endraw %}{%- for controller_name, controller in cg.controller.iteritems() -%}{{ controller_name }}{%- if not loop.last -%},{%- endif -%}{%- endfor -%}{% raw %}         {% endraw %}{{ cgroup_name }}
+{%- endfor %}
+{%- endfor %}
diff --git a/linux/system/cgroup.sls b/linux/system/cgroup.sls
new file mode 100644
index 0000000..caac31c
--- /dev/null
+++ b/linux/system/cgroup.sls
@@ -0,0 +1,119 @@
+{%- from "linux/map.jinja" import system with context %}
+
+{%- if system.cgroup.enabled|default(True) %}
+
+cgroup_package:
+  pkg.installed:
+  - pkgs:
+    - cgroup-bin
+
+include:
+  - linux.system.grub
+
+/etc/default/grub.d/80-cgroup.cfg:
+  file.managed:
+  - contents: 'GRUB_CMDLINE_LINUX_DEFAULT="quiet cgroup_enable=memory swapaccount=1"'
+  - require:
+    - file: grub_d_directory
+{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
+  - watch_in:
+    - cmd: grub_update
+{%- endif %}
+
+/etc/cgconfig.conf:
+  file.managed:
+  - user: root
+  - group: root
+  - mode: 0644
+  - template: jinja
+  - source: salt://linux/files/cgconfig.conf
+{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
+  - check_cmd: /usr/sbin/cgconfigparser -l
+{%- endif %}
+
+/etc/cgrules.conf:
+  file.managed:
+  - user: root
+  - group: root
+  - mode: 0644
+  - template: jinja
+  - source: salt://linux/files/cgrules.conf
+
+/etc/default/cgred:
+  file.managed:
+  - contents: |
+      OPTIONS=-v --logfile=/var/log/cgrulesengd.log
+
+/etc/systemd/system/cgred.service:
+  file.managed:
+  - contents: |
+      [Unit]
+      Description=CGroups Rules Engine Daemon
+      After=syslog.target
+
+      [Service]
+      Type=forking
+      EnvironmentFile=-/etc/default/cgred
+      ExecStart=/usr/sbin/cgrulesengd $OPTIONS
+
+      [Install]
+      WantedBy=multi-user.target
+
+cgred_service_running:
+  service.running:
+  - enable: true
+  - names: ['cgred']
+  - watch:
+    - file: /etc/cgconfig.conf
+    - file: /etc/cgrules.conf
+    - file: /etc/default/cgred
+    - file: /etc/systemd/system/cgred.service
+  {%- if grains.get('noservices') %}
+  - onlyif: /bin/false
+  {%- endif %}
+
+{%- else %}
+
+cgred_service_dead:
+  service.dead:
+  - enable: false
+  - names: ['cgred']
+  {%- if grains.get('noservices') %}
+  - onlyif: /bin/false
+  {%- endif %}
+
+include:
+  - linux.system.grub
+
+remove_/etc/default/grub.d/80-cgroup.cfg:
+  file.absent:
+  - name: /etc/default/grub.d/80-cgroup.cfg
+  - require:
+    - file: grub_d_directory
+{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
+  - watch_in:
+    - cmd: grub_update
+{%- endif %}
+
+remove_/etc/systemd/system/cgred.service:
+  file.absent:
+  - name: /etc/systemd/system/cgred.service
+
+remove_/etc/cgconfig.conf:
+  file.absent:
+  - name: /etc/cgconfig.conf
+
+remove_/etc/cgrules.conf:
+  file.absent:
+  - name: /etc/cgrules.conf
+
+remove_/etc/default/cgred:
+  file.absent:
+  - name: /etc/default/cgred
+
+purge_cgroup_package:
+  pkg.purged:
+  - pkgs:
+    - cgroup-tools
+
+{%- endif %}
diff --git a/linux/system/init.sls b/linux/system/init.sls
index 25008a8..af61698 100644
--- a/linux/system/init.sls
+++ b/linux/system/init.sls
@@ -33,6 +33,9 @@
 {%- if system.sysfs is defined %}
 - linux.system.sysfs
 {%- endif %}
+{%- if system.cgroup is defined %}
+- linux.system.cgroup
+{%- endif %}
 {%- if system.locale|length > 0 %}
 - linux.system.locale
 {%- endif %}
diff --git a/tests/pillar/system.sls b/tests/pillar/system.sls
index 06a1bdc..497aee2 100644
--- a/tests/pillar/system.sls
+++ b/tests/pillar/system.sls
@@ -19,6 +19,16 @@
     kernel:
       isolcpu: 1,2,3,4
       elevator: deadline
+    cgroup:
+      group:
+        group_1:
+          controller:
+            cpu:
+              shares:
+                value: 250
+          mapping:
+            subjects:
+            - '@group1'
     sysfs:
       scheduler:
         block/sda/queue/scheduler: deadline