Added support for salt engines, added support for requisite ordering

Change-Id: I772495c38ed5dc21ad833f3c0f351384942e2b23
diff --git a/_engines/saltgraph.py b/_engines/saltgraph.py
index 0287449..b70af19 100644
--- a/_engines/saltgraph.py
+++ b/_engines/saltgraph.py
@@ -194,7 +194,7 @@
             opts=__opts__,
             sock_dir=__opts__['sock_dir'],
             listen=True)
-        log.debug('Saltgraph engine started')
+    log.debug('Saltgraph engine started')
 
     while True:
         event = event_bus.get_event()
diff --git a/_modules/modelutils.py b/_modules/modelutils.py
new file mode 100644
index 0000000..6d0ab40
--- /dev/null
+++ b/_modules/modelutils.py
@@ -0,0 +1,75 @@
+
+from collections import OrderedDict
+
+
+def __virtual__():
+    return True
+
+
+def _set_subtree(node, relationships):
+    return {
+        v: _set_subtree(v, relationships)
+        for v in [x['id'] for x in relationships if node in x['require']]
+    }
+
+
+def _traverse_subtree(output, data):
+    for key, value in data.items():
+        output.append(key)
+        _traverse_subtree(output, value)
+    return output
+
+
+def order_by_requisites(data):
+    '''
+    Returns dictionary ordered by require and require_by
+
+    CLI Examples:
+
+    .. code-block:: bash
+
+        salt-call modelutils.order_by_requisites "{'dict':'value'}""
+
+    Sample data
+
+    passed_data:
+      syslog2:
+        pattern: 'syslog.*'
+      syslog_tele1:
+        type: parser
+        require:
+        - syslog1
+      syslog1:
+        pattern: 'syslog.*'
+        require_in:
+        - syslog2
+      syslog_tele2:
+        require:
+        - syslog_tele1
+
+    '''
+    raw_key_list = []
+    ordered_key_list = []
+    output_dict = OrderedDict()
+
+    for datum_id, datum in data.items():
+        if 'require_in' in datum:
+            for req in datum['require_in']:
+                if 'require' not in data[req]:
+                    data[req]['require'] = []
+                data[req]['require'].append(datum_id)
+            datum.pop('require_in')
+
+    for datum_id, datum in data.items():
+        if 'require' not in datum:
+            datum['require'] = ['top']
+        datum['id'] = datum_id
+        raw_key_list.append(datum)
+
+    tree_data = _set_subtree('top', raw_key_list)
+    _traverse_subtree(ordered_key_list, tree_data)
+    for key in ordered_key_list:
+        output_dict[key] = data[key]
+
+    return output_dict
+
diff --git a/salt/files/_engine.conf b/salt/files/_engine.conf
index 7d80849..7edee8e 100644
--- a/salt/files/_engine.conf
+++ b/salt/files/_engine.conf
@@ -1,5 +1,10 @@
 {% from "salt/map.jinja" import master with context %}
 
+engines_dirs:
+{%- for environment_name, environment in master.get('environment', {}).iteritems() %}
+- /srv/salt/env/{{ environment_name }}/_engines
+{%- endfor %}
+
 engines:
 {%- for engine_name, engine in master.engine.items() %}
 {%- set name = engine.get('engine', engine_name) %}
diff --git a/salt/master/env.sls b/salt/master/env.sls
index 4568e20..36a927e 100644
--- a/salt/master/env.sls
+++ b/salt/master/env.sls
@@ -114,6 +114,8 @@
     - /usr/share/salt-formulas/env/_states
     - /usr/share/salt-formulas/env/_grains
     - /usr/share/salt-formulas/env/_formulas
+    - /usr/share/salt-formulas/env/_engines
+    - /usr/share/salt-formulas/env/_runners
   - makedirs: True
 
 salt_env_{{ environment_name }}_dirs:
@@ -132,6 +134,8 @@
     - /srv/salt/env/{{ environment_name }}/_states
     - /srv/salt/env/{{ environment_name }}/_grains
     - /srv/salt/env/{{ environment_name }}/_formulas
+    - /srv/salt/env/{{ environment_name }}/_engines
+    - /srv/salt/env/{{ environment_name }}/_runners
   - makedirs: True
 
 {%- endif %}
@@ -332,7 +336,7 @@
 
 {%- for engine_name, engine in formula.get('engine', {}).iteritems() %}
 
-salt_master_{{ environment_name }}_{{ engine_name }}_state:
+salt_master_{{ environment_name }}_{{ engine_name }}_engine:
   file.symlink:
   - name: /srv/salt/env/{{ environment_name }}/_engines/{{ engine_name }}
   - target: /srv/salt/env/{{ environment_name }}/_formulas/{{ formula_name }}/_engines/{{ engine_name }}
@@ -341,6 +345,17 @@
 
 {%- endfor %}
 
+{%- for runner_name, runner in formula.get('runner', {}).iteritems() %}
+
+salt_master_{{ environment_name }}_{{ runner_name }}_runner:
+  file.symlink:
+  - name: /srv/salt/env/{{ environment_name }}/_engines/{{ runner_name }}
+  - target: /srv/salt/env/{{ environment_name }}/_formulas/{{ formula_name }}/_engines/{{ runner_name }}
+  - force: True
+  - makedirs: True
+
+{%- endfor %}
+
 {%- endif %}
 
 {%- endif %}