SOA relations modeling

Change-Id: Icd6334902ca47d83ae263905d65ef91b8e6a7335
diff --git a/salt/meta/meta.yml b/salt/meta/meta.yml
new file mode 100644
index 0000000..0a60473
--- /dev/null
+++ b/salt/meta/meta.yml
@@ -0,0 +1,31 @@
+graph:
+{%- if pillar.get('salt', {}).minion is defined %}
+{%- from "salt/map.jinja" import minion with context %}
+- host: {{ grains.id }}
+  service: salt.minion
+  type: software-config
+  relations:
+  {%- if minion.master is defined %}
+  - service: salt-master
+    {%- if minion.master.host in ['127.0.0.1', 'localhost'] %}
+    host: {{ grains.id }}
+    {%- else %}
+    host_from_target: {{ minion.master.host }}
+    {%- endif %}
+    direction: source
+    type: tcp-0mq
+  {%- endif %}
+{%- endif %}
+{%- if pillar.get('salt', {}).master is defined %}
+{%- from "salt/map.jinja" import master with context %}
+- host: {{ grains.id }}
+  service: salt.master
+  type: software-config
+  relations:
+  {%- if master.pillar.engine == 'reclass' %}
+  - host: {{ grains.id }}
+    service: reclass.storage
+    direction: source
+    type: local-file
+  {%- endif %}
+{%- endif %}
diff --git a/salt/meta/salt.yml b/salt/meta/salt.yml
index 1a97657..9d6a728 100644
--- a/salt/meta/salt.yml
+++ b/salt/meta/salt.yml
@@ -1,3 +1,17 @@
+{%- set service_grains = {'salt': {'graph': []}} %}
+{%- for service_name, service in pillar.items() %}
+  {%- set grains_fragment_file = service_name+'/meta/meta.yml' %}
+  {%- macro load_grains_file() %}{% include grains_fragment_file ignore missing %}{% endmacro %}
+  {%- set grains_yaml = load_grains_file()|load_yaml %}
+  {%- if grains_yaml is mapping %}
+    {%- for node in grains_yaml.graph %}
+    {%- do service_grains.salt.graph.append(node) %}
+    {%- endfor %}
+  {%- endif %}
+{%- endfor %}
+grain:
+  salt:
+    {{ service_grains|yaml(False)|indent(4) }}
 orchestrate:
   master:
     priority: 60
@@ -7,7 +21,6 @@
     priority: 400
     require:
     - salt: salt.master
-
 minion:
   {%- if pillar.get('salt', {}).get('minion', {}).get('ca') %}
   pki: