Add support for sysfs

Change-Id: I29cfe2cd9dd39b74a1d39313f78dfddc87cb79b8
diff --git a/README.rst b/README.rst
index 9e1692b..9a3a5a5 100644
--- a/README.rst
+++ b/README.rst
@@ -407,6 +407,25 @@
         cpu:
           governor: performance
 
+Sysfs
+~~~~~
+
+Install sysfsutils and set sysfs attributes:
+
+.. code-block:: yaml
+
+    linux:
+      system:
+        sysfs:
+          scheduler:
+            block/sda/queue/scheduler: deadline
+          power:
+            mode:
+              power/state: 0660
+            owner:
+              power/state: "root:power"
+            devices/system/cpu/cpu0/cpufreq/scaling_governor: powersave
+
 Huge Pages
 ~~~~~~~~~~~~
 
diff --git a/linux/files/sysfs.conf b/linux/files/sysfs.conf
new file mode 100644
index 0000000..513a53a
--- /dev/null
+++ b/linux/files/sysfs.conf
@@ -0,0 +1,16 @@
+# Sysfs file for {{ name }} managed by salt-minion(1)
+#   DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+
+{%- for key, value in sysfs.iteritems() %}
+  {%- if key in ["mode", "owner"] %}
+    {%- for attr, val in value.iteritems() %}
+mode {{ attr }} = {{ val }}
+    {%- endfor %}
+  {%- else %}
+{{ key }} = {{ value }}
+  {%- endif %}
+{%- endfor %}
+
+{#-
+vim: syntax=jinja
+-#}
diff --git a/linux/system/cpu.sls b/linux/system/cpu.sls
index 4bf6564..37c3c21 100644
--- a/linux/system/cpu.sls
+++ b/linux/system/cpu.sls
@@ -1,16 +1,8 @@
 {%- from "linux/map.jinja" import system with context %}
 {%- if system.cpu.governor is defined %}
 
-linux_sysfs_package:
-  pkg.installed:
-    - pkgs:
-      - sysfsutils
-    - refresh: true
-
-/etc/sysfs.d:
-  file.directory:
-    - require:
-      - pkg: linux_sysfs_package
+include:
+  - linux.system.sysfs
 
 ondemand_service_disable:
   service.dead:
diff --git a/linux/system/init.sls b/linux/system/init.sls
index fe54147..0ba87aa 100644
--- a/linux/system/init.sls
+++ b/linux/system/init.sls
@@ -30,6 +30,9 @@
 {%- if system.cpu is defined %}
 - linux.system.cpu
 {%- endif %}
+{%- if system.sysfs is defined %}
+- linux.system.sysfs
+{%- endif %}
 {%- if system.locale|length > 0 %}
 - linux.system.locale
 {%- endif %}
diff --git a/linux/system/sysfs.sls b/linux/system/sysfs.sls
new file mode 100644
index 0000000..fdf1686
--- /dev/null
+++ b/linux/system/sysfs.sls
@@ -0,0 +1,42 @@
+{%- from "linux/map.jinja" import system with context %}
+
+linux_sysfs_package:
+  pkg.installed:
+    - pkgs:
+      - sysfsutils
+    - refresh: true
+
+/etc/sysfs.d:
+  file.directory:
+    - require:
+      - pkg: linux_sysfs_package
+
+{%- for name, sysfs in system.get('sysfs', {}).iteritems() %}
+
+/etc/sysfs.d/{{ name }}.conf:
+  file.managed:
+    - source: salt://linux/files/sysfs.conf
+    - template: jinja
+    - user: root
+    - group: root
+    - mode: 0644
+    - defaults:
+        name: {{ name }}
+        sysfs: {{ sysfs|yaml }}
+    - require:
+      - file: /etc/sysfs.d
+
+  {%- for key, value in sysfs.iteritems() %}
+    {%- if key not in ["mode", "owner"] %}
+      {%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
+      {#- Sysfs cannot be set in docker, LXC, etc. #}
+linux_sysfs_write_{{ name }}_{{ key }}:
+  module.run:
+    - name: sysfs.write
+    - key: {{ key }}
+    - value: {{ value }}
+      {%- endif %}
+    {%- endif %}
+  {%- endfor %}
+
+{%- endfor %}
diff --git a/tests/pillar/system.sls b/tests/pillar/system.sls
index 8d39312..f39fdde 100644
--- a/tests/pillar/system.sls
+++ b/tests/pillar/system.sls
@@ -15,6 +15,15 @@
       default: "linux.ci.local$"
     kernel:
       isolcpu: 1,2,3,4
+    sysfs:
+      scheduler:
+        block/sda/queue/scheduler: deadline
+      power:
+        mode:
+          power/state: 0660
+        owner:
+          power/state: "root:power"
+        devices/system/cpu/cpu0/cpufreq/scaling_governor: powersave
     motd:
       - warning: |
           #!/bin/sh