Add ability to pass hardware metadata

Related-Prod: PRODX-00000
Change-Id: I4c377558ffe13e28f8ac5ced45262ff67556f46c
diff --git a/de/heat-templates/env/bmt402-mstr1-wrkr3-cmp0-gtw0.yaml b/de/heat-templates/env/bmt402-mstr1-wrkr3-cmp0-gtw0.yaml
index c195d1d..0c8b3bc 100644
--- a/de/heat-templates/env/bmt402-mstr1-wrkr3-cmp0-gtw0.yaml
+++ b/de/heat-templates/env/bmt402-mstr1-wrkr3-cmp0-gtw0.yaml
@@ -94,3 +94,87 @@
         # NOTE(vsaienko): give some time to apply changes
         sleep 15
     }
+  hardware_metadata: |
+    '0c:c4:7a:20:19:8a':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            # The roles will be assigned based on node labels.
+            # roles:
+            #   - mon
+            #   - mgr
+            ips:
+              - 192.168.122.101
+            crushPath: {}
+
+    '0c:c4:7a:20:19:28':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.102
+            crushPath: {}
+    '0c:c4:7a:20:19:48':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.103
+            crushPath: {}
+    '0c:c4:7a:20:15:28':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.104
+            crushPath: {}
+    '0c:c4:7a:20:19:46':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.105
+            crushPath: {}
+    '0c:c4:7a:17:90:66':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.106
+            crushPath: {}
diff --git a/de/heat-templates/env/bmt402-mstr1-wrkr3-cmp2-gtw0.yaml b/de/heat-templates/env/bmt402-mstr1-wrkr3-cmp2-gtw0.yaml
index d333f28..3fefa93 100644
--- a/de/heat-templates/env/bmt402-mstr1-wrkr3-cmp2-gtw0.yaml
+++ b/de/heat-templates/env/bmt402-mstr1-wrkr3-cmp2-gtw0.yaml
@@ -94,3 +94,87 @@
         # NOTE(vsaienko): give some time to apply changes
         sleep 15
     }
+  hardware_metadata: |
+    '0c:c4:7a:20:19:8a':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            # The roles will be assigned based on node labels.
+            # roles:
+            #   - mon
+            #   - mgr
+            ips:
+              - 192.168.122.101
+            crushPath: {}
+
+    '0c:c4:7a:20:19:28':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.102
+            crushPath: {}
+    '0c:c4:7a:20:19:48':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.103
+            crushPath: {}
+    '0c:c4:7a:20:15:28':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.104
+            crushPath: {}
+    '0c:c4:7a:20:19:46':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.105
+            crushPath: {}
+    '0c:c4:7a:17:90:66':
+      write_files:
+        - path: /usr/share/metadata/ceph.yaml
+          content: |
+            storageDevices:
+              - name: sdb
+                role: hdd
+                sizeGb: 450
+            ram: 64
+            cores: 12
+            ips:
+              - 192.168.122.106
+            crushPath: {}
diff --git a/de/heat-templates/env/compute.yaml b/de/heat-templates/env/compute.yaml
index 0a2bf60..eb31703 100644
--- a/de/heat-templates/env/compute.yaml
+++ b/de/heat-templates/env/compute.yaml
@@ -23,3 +23,4 @@
   worker_metadata: {"labels": {"openstack-control-plane":"enabled","openvswitch":"enabled","role":"ceph-osd-node"}}
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/converged.yaml b/de/heat-templates/env/converged.yaml
index 041dfcb..9448af4 100644
--- a/de/heat-templates/env/converged.yaml
+++ b/de/heat-templates/env/converged.yaml
@@ -23,3 +23,4 @@
   worker_metadata: {"labels": {"openstack-control-plane":"enabled","openstack-compute-node":"enabled","openvswitch":"enabled","role":"ceph-osd-node"}}
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr1-wrkr3-cmp0-gtw0-lma3.yaml b/de/heat-templates/env/mstr1-wrkr3-cmp0-gtw0-lma3.yaml
index eeba1db..c1b44d6 100644
--- a/de/heat-templates/env/mstr1-wrkr3-cmp0-gtw0-lma3.yaml
+++ b/de/heat-templates/env/mstr1-wrkr3-cmp0-gtw0-lma3.yaml
@@ -25,3 +25,4 @@
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
   lma_metadata: {"labels": {"role": "stacklight", "stacklight": "enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr1-wrkr3-cmp0-gtw0.yaml b/de/heat-templates/env/mstr1-wrkr3-cmp0-gtw0.yaml
index e97ebd1..755e66f 100644
--- a/de/heat-templates/env/mstr1-wrkr3-cmp0-gtw0.yaml
+++ b/de/heat-templates/env/mstr1-wrkr3-cmp0-gtw0.yaml
@@ -23,3 +23,4 @@
   worker_metadata: {"labels": {"openstack-control-plane":"enabled","openstack-compute-node":"enabled","openvswitch":"enabled", "openstack-gateway":"enabled","role":"ceph-osd-node"}}
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0-lma3.yaml b/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0-lma3.yaml
index ddd3b9c..74c9f0d 100644
--- a/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0-lma3.yaml
+++ b/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0-lma3.yaml
@@ -25,3 +25,4 @@
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
   lma_metadata: {"labels": {"role": "stacklight", "stacklight": "enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0.yaml b/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0.yaml
index 11ec72e..0963dc1 100644
--- a/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0.yaml
+++ b/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0.yaml
@@ -23,3 +23,4 @@
   worker_metadata: {"labels": {"openstack-control-plane":"enabled","openvswitch":"enabled","role":"ceph-osd-node"}}
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr1-wrkr3-cmp3-gtw0.yaml b/de/heat-templates/env/mstr1-wrkr3-cmp3-gtw0.yaml
index 1ec040a..98e4217 100644
--- a/de/heat-templates/env/mstr1-wrkr3-cmp3-gtw0.yaml
+++ b/de/heat-templates/env/mstr1-wrkr3-cmp3-gtw0.yaml
@@ -23,3 +23,4 @@
   worker_metadata: {"labels": {"openstack-control-plane":"enabled","openvswitch":"enabled","openstack-gateway":"enabled","role":"ceph-osd-node"}}
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr1-wrkr5-cmp0-gtw0.yaml b/de/heat-templates/env/mstr1-wrkr5-cmp0-gtw0.yaml
index 03c19c8..0027bb2 100644
--- a/de/heat-templates/env/mstr1-wrkr5-cmp0-gtw0.yaml
+++ b/de/heat-templates/env/mstr1-wrkr5-cmp0-gtw0.yaml
@@ -23,3 +23,4 @@
   worker_metadata: {"labels": {"openstack-control-plane":"enabled","openstack-compute-node":"enabled","openvswitch":"enabled","openstack-gateway":"enabled","role":"ceph-osd-node"}}
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr1-wrkr5-cmp2-gtw0.yaml b/de/heat-templates/env/mstr1-wrkr5-cmp2-gtw0.yaml
index c01e123..c35ef74 100644
--- a/de/heat-templates/env/mstr1-wrkr5-cmp2-gtw0.yaml
+++ b/de/heat-templates/env/mstr1-wrkr5-cmp2-gtw0.yaml
@@ -23,3 +23,4 @@
   worker_metadata: {"labels": {"openstack-control-plane":"enabled","openvswitch":"enabled","openstack-gateway":"enabled","role":"ceph-osd-node"}}
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp0-gtw0-lma3.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp0-gtw0-lma3.yaml
index c247aed..2620ae0 100644
--- a/de/heat-templates/env/mstr3-wrkr3-cmp0-gtw0-lma3.yaml
+++ b/de/heat-templates/env/mstr3-wrkr3-cmp0-gtw0-lma3.yaml
@@ -25,3 +25,4 @@
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
   lma_metadata: {"labels": {"role": "stacklight", "stacklight": "enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp0-gtw0.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp0-gtw0.yaml
new file mode 100644
index 0000000..ae3b3b2
--- /dev/null
+++ b/de/heat-templates/env/mstr3-wrkr3-cmp0-gtw0.yaml
@@ -0,0 +1,23 @@
+resource_registry:
+  "MCP2::NetworkAcc": ../fragments/NetworkAccVM.yaml
+  "MCP2::NetworkPrvFl": ../fragments/NetworkPrvFl.yaml
+  "MCP2::SrvInstances": ../fragments/SrvInstancesVM.yaml
+
+parameters:
+  image: bionic-server-cloudimg-amd64-20190612
+  public_net_id: public
+  host_interface: 'ens3'
+  masters_size: 2
+  worker_size: 3
+  cmp_size: 0
+  gtw_size: 0
+  lma_size: 0
+  osd_size: 0
+  ucp_boot_timeout: 1200
+  cluster_public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCp0evjOaK8c8SKYK4r2+0BN7g+8YSvQ2n8nFgOURCyvkJqOHi1qPGZmuN0CclYVdVuZiXbWw3VxRbSW3EH736VzgY1U0JmoTiSamzLHaWsXvEIW8VCi7boli539QJP0ikJiBaNAgZILyCrVPN+A6mfqtacs1KXdZ0zlMq1BPtFciR1JTCRcVs5vP2Wwz5QtY2jMIh3aiwkePjMTQPcfmh1TkOlxYu5IbQyZ3G1ahA0mNKI9a0dtF282av/F6pwB/N1R1nEZ/9VtcN2I1mf1NW/tTHEEcTzXYo1R/8K9vlqAN8QvvGLZtZduGviNVNoNWvoxaXxDt8CPv2B2NCdQFZp
+  private_floating_network_cidr: '10.11.12.0/24'
+  private_floating_interface: 'ens4'
+  worker_metadata: {"labels": {"openstack-control-plane":"enabled","openstack-compute-node":"enabled","openvswitch":"enabled","role":"ceph-osd-node"}}
+  cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
+  gtw_metadata: {"labels": {"openvswitch":"enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0-lma3-osd3.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0-lma3-osd3.yaml
index 7d1cd0c..cb3dc1a 100644
--- a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0-lma3-osd3.yaml
+++ b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0-lma3-osd3.yaml
@@ -32,3 +32,4 @@
   gtw_metadata: {"labels": {"openvswitch":"enabled", "openstack-gateway": "enabled"}}
   lma_metadata: {"labels": {"role": "stacklight", "stacklight": "enabled"}}
   osd_metadata: {"labels": {"role": "ceph-osd-node"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0-lma3.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0-lma3.yaml
index 5e84844..167c808 100644
--- a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0-lma3.yaml
+++ b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0-lma3.yaml
@@ -25,3 +25,4 @@
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled"}}
   lma_metadata: {"labels": {"role": "stacklight", "stacklight": "enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0.yaml
deleted file mode 120000
index 67c5dde..0000000
--- a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0.yaml
+++ /dev/null
@@ -1 +0,0 @@
-compute.yaml
\ No newline at end of file
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0.yaml
new file mode 100644
index 0000000..792b50d
--- /dev/null
+++ b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw0.yaml
@@ -0,0 +1,23 @@
+resource_registry:
+  "MCP2::NetworkAcc": ../fragments/NetworkAccVM.yaml
+  "MCP2::NetworkPrvFl": ../fragments/NetworkPrvFl.yaml
+  "MCP2::SrvInstances": ../fragments/SrvInstancesVM.yaml
+
+parameters:
+  image: bionic-server-cloudimg-amd64-20190612
+  public_net_id: public
+  host_interface: 'ens3'
+  masters_size: 2
+  worker_size: 3
+  cmp_size: 2
+  gtw_size: 0
+  lma_size: 0
+  osd_size: 0
+  ucp_boot_timeout: 1200
+  cluster_public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCp0evjOaK8c8SKYK4r2+0BN7g+8YSvQ2n8nFgOURCyvkJqOHi1qPGZmuN0CclYVdVuZiXbWw3VxRbSW3EH736VzgY1U0JmoTiSamzLHaWsXvEIW8VCi7boli539QJP0ikJiBaNAgZILyCrVPN+A6mfqtacs1KXdZ0zlMq1BPtFciR1JTCRcVs5vP2Wwz5QtY2jMIh3aiwkePjMTQPcfmh1TkOlxYu5IbQyZ3G1ahA0mNKI9a0dtF282av/F6pwB/N1R1nEZ/9VtcN2I1mf1NW/tTHEEcTzXYo1R/8K9vlqAN8QvvGLZtZduGviNVNoNWvoxaXxDt8CPv2B2NCdQFZp
+  private_floating_network_cidr: '10.11.12.0/24'
+  private_floating_interface: 'ens4'
+  worker_metadata: {"labels": {"openstack-control-plane":"enabled","openvswitch":"enabled","role":"ceph-osd-node"}}
+  cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
+  gtw_metadata: {"labels": {"openvswitch":"enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw2.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw2.yaml
deleted file mode 120000
index a7cc910..0000000
--- a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw2.yaml
+++ /dev/null
@@ -1 +0,0 @@
-telco.yaml
\ No newline at end of file
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw2.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw2.yaml
new file mode 100644
index 0000000..8649095
--- /dev/null
+++ b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw2.yaml
@@ -0,0 +1,23 @@
+resource_registry:
+  "MCP2::NetworkAcc": ../fragments/NetworkAccVM.yaml
+  "MCP2::NetworkPrvFl": ../fragments/NetworkPrvFl.yaml
+  "MCP2::SrvInstances": ../fragments/SrvInstancesVM.yaml
+
+parameters:
+  image: bionic-server-cloudimg-amd64-20190612
+  public_net_id: public
+  host_interface: 'ens3'
+  masters_size: 2
+  worker_size: 3
+  cmp_size: 2
+  gtw_size: 2
+  lma_size: 0
+  osd_size: 0
+  ucp_boot_timeout: 1200
+  cluster_public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCp0evjOaK8c8SKYK4r2+0BN7g+8YSvQ2n8nFgOURCyvkJqOHi1qPGZmuN0CclYVdVuZiXbWw3VxRbSW3EH736VzgY1U0JmoTiSamzLHaWsXvEIW8VCi7boli539QJP0ikJiBaNAgZILyCrVPN+A6mfqtacs1KXdZ0zlMq1BPtFciR1JTCRcVs5vP2Wwz5QtY2jMIh3aiwkePjMTQPcfmh1TkOlxYu5IbQyZ3G1ahA0mNKI9a0dtF282av/F6pwB/N1R1nEZ/9VtcN2I1mf1NW/tTHEEcTzXYo1R/8K9vlqAN8QvvGLZtZduGviNVNoNWvoxaXxDt8CPv2B2NCdQFZp
+  private_floating_network_cidr: '10.11.12.0/24'
+  private_floating_interface: 'ens4'
+  worker_metadata: {"labels": {"openstack-control-plane":"enabled","role":"ceph-osd-node"}}
+  cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
+  gtw_metadata: {"labels": {"openvswitch":"enabled", "openstack-gateway": "enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw3-lma3-osd3.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw3-lma3-osd3.yaml
index 2f17823..e9be351 100644
--- a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw3-lma3-osd3.yaml
+++ b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw3-lma3-osd3.yaml
@@ -32,3 +32,4 @@
   gtw_metadata: {"labels": {"openvswitch":"enabled", "openstack-gateway": "enabled"}}
   lma_metadata: {"labels": {"role": "stacklight", "stacklight": "enabled"}}
   osd_metadata: {"labels": {"role": "ceph-osd-node"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw3-lma3.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw3-lma3.yaml
index 42ef343..50dcd10 100644
--- a/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw3-lma3.yaml
+++ b/de/heat-templates/env/mstr3-wrkr3-cmp2-gtw3-lma3.yaml
@@ -24,3 +24,4 @@
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled", "openstack-gateway": "enabled"}}
   lma_metadata: {"labels": {"role": "stacklight", "stacklight": "enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr3-cmp2-ntw3-lma3-osd3.yaml b/de/heat-templates/env/mstr3-wrkr3-cmp2-ntw3-lma3-osd3.yaml
index dd9cc99..e888cad 100644
--- a/de/heat-templates/env/mstr3-wrkr3-cmp2-ntw3-lma3-osd3.yaml
+++ b/de/heat-templates/env/mstr3-wrkr3-cmp2-ntw3-lma3-osd3.yaml
@@ -33,3 +33,4 @@
   lma_metadata: {"labels": {"role": "stacklight", "stacklight": "enabled"}}
   osd_metadata: {"labels": {"role": "ceph-osd-node"}}
   ntw_metadata: {"labels": {"tfanalytics": "enabled", "tfconfig": "enabled", "tfcontrol": "enabled", "tfwebui": "enabled", "tfconfigdb": "enabled", "tfanalyticsdb": "enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/mstr3-wrkr6-cmp3-osd3.yaml b/de/heat-templates/env/mstr3-wrkr6-cmp3-osd3.yaml
index 8688a2a..f09a354 100644
--- a/de/heat-templates/env/mstr3-wrkr6-cmp3-osd3.yaml
+++ b/de/heat-templates/env/mstr3-wrkr6-cmp3-osd3.yaml
@@ -32,3 +32,4 @@
   gtw_metadata: {"labels": {"openvswitch":"enabled", "openstack-gateway": "enabled"}}
   lma_metadata: {"labels": {"role": "stacklight", "stacklight": "enabled"}}
   osd_metadata: {"labels": {"role": "ceph-osd-node"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/env/telco.yaml b/de/heat-templates/env/telco.yaml
index e884ddb..1a5f73a 100644
--- a/de/heat-templates/env/telco.yaml
+++ b/de/heat-templates/env/telco.yaml
@@ -23,3 +23,4 @@
   worker_metadata: {"labels": {"openstack-control-plane":"enabled","role":"ceph-osd-node"}}
   cmp_metadata: {"labels": {"openstack-compute-node":"enabled","openvswitch":"enabled", "role":"ceph-osd-node"}}
   gtw_metadata: {"labels": {"openvswitch":"enabled", "openstack-gateway": "enabled"}}
+  hardware_metadata: ''
diff --git a/de/heat-templates/fragments/SrvInstancesBM.yaml b/de/heat-templates/fragments/SrvInstancesBM.yaml
index 46f8e68..cf247db 100644
--- a/de/heat-templates/fragments/SrvInstancesBM.yaml
+++ b/de/heat-templates/fragments/SrvInstancesBM.yaml
@@ -46,6 +46,10 @@
     type: string
   docker_ee_url:
     type: string
+  hardware_metadata:
+    description: The content of lab metadata.
+    default: ''
+    type: string
 
 resources:
 
@@ -70,6 +74,27 @@
             $private_floating_interface_ip: { get_attr: [private_floating_server_port, fixed_ips, 0, ip_address] }
             $functions_override: { get_param: functions_override }
 
+  inject_files:
+    type: "OS::Heat::CloudConfig"
+    properties:
+      cloud_config:
+        write_files:
+          - path: /usr/sbin/prepare-metadata.py
+            owner: "root:root"
+            permissions: "0755"
+            content: {get_file: ../scripts/prepare-metadata.py}
+          - path: /usr/share/metadata/lab-metadata.yaml
+            owner: "root:root"
+            permissions: "0644"
+            content: { get_param: hardware_metadata}
+
+  install_config_agent:
+    type: "OS::Heat::MultipartMime"
+    properties:
+      parts:
+      - config: {get_resource: software_config}
+      - config: {get_resource: inject_files}
+
   server:
     type: OS::Nova::Server
     properties:
@@ -81,8 +106,8 @@
         - network: { get_param: accessible_network }
         # NOTE(ohryhorov): connect to accessible network only as ironic doesn't
         # support multitenancy use-case. Use private_floating_network for IPAM only.
-      user_data_format: RAW
-      user_data: { get_resource: software_config }
+      user_data_format: SOFTWARE_CONFIG
+      user_data: { get_resource:  install_config_agent}
       metadata: { get_param: metadata }
 
   private_floating_server_port:
@@ -112,3 +137,6 @@
   server_public_ip:
     description: Floating IP address of server in public network
     value: { get_attr: [server, networks, { get_param: accessible_network}, 0]}
+  wc_data:
+    description: Metadata from instance
+    value: { get_attr: [wait_condition, data]}
diff --git a/de/heat-templates/fragments/SrvInstancesBMCeph.yaml b/de/heat-templates/fragments/SrvInstancesBMCeph.yaml
index 95a8b97..3bd4369 100644
--- a/de/heat-templates/fragments/SrvInstancesBMCeph.yaml
+++ b/de/heat-templates/fragments/SrvInstancesBMCeph.yaml
@@ -54,6 +54,9 @@
     type: string
   docker_ee_url:
     type: string
+  hardware_metadata:
+    description: The content of lab metadata.
+    type: string
 
 resources:
 
@@ -81,6 +84,27 @@
             $storage_frontend_network_interface_ip: { get_attr: [storage_frontend_server_port, fixed_ips, 0, ip_address] }
             $storage_frontend_network_cidr: { get_param: storage_frontend_network_cidr }
 
+  inject_files:
+    type: "OS::Heat::CloudConfig"
+    properties:
+      cloud_config:
+        write_files:
+          - path: /usr/sbin/prepare-metadata.py
+            owner: "root:root"
+            permissions: "0755"
+            content: {get_file: ../scripts/prepare-metadata.py}
+          - path: /usr/share/metadata/lab-metadata.yaml
+            owner: "root:root"
+            permissions: "0644"
+            content: { get_param: hardware_metadata}
+
+  install_config_agent:
+    type: "OS::Heat::MultipartMime"
+    properties:
+      parts:
+      - config: {get_resource: software_config}
+      - config: {get_resource: inject_files}
+
   server:
     type: OS::Nova::Server
     properties:
@@ -92,8 +116,8 @@
         - network: { get_param: accessible_network }
         # NOTE(ohryhorov): connect to accessible network only as ironic doesn't
         # support multitenancy use-case. Use private_floating_network for IPAM only.
-      user_data_format: RAW
-      user_data: { get_resource: software_config }
+      user_data_format: SOFTWARE_CONFIG
+      user_data: { get_resource:  install_config_agent}
       metadata: { get_param: metadata }
 
   private_floating_server_port:
@@ -131,3 +155,6 @@
   server_public_ip:
     description: Floating IP address of server in public network
     value: { get_attr: [server, networks, { get_param: accessible_network}, 0]}
+  wc_data:
+    description: Metadata from instance
+    value: { get_attr: [wait_condition, data]}
diff --git a/de/heat-templates/fragments/SrvInstancesBMCephOSD.yaml b/de/heat-templates/fragments/SrvInstancesBMCephOSD.yaml
index 0991319..92fa9c5 100644
--- a/de/heat-templates/fragments/SrvInstancesBMCephOSD.yaml
+++ b/de/heat-templates/fragments/SrvInstancesBMCephOSD.yaml
@@ -62,6 +62,9 @@
     type: string
   docker_ee_url:
     type: string
+  hardware_metadata:
+    description: The content of lab metadata.
+    type: string
 
 resources:
 
@@ -92,6 +95,27 @@
             $storage_backend_network_interface_ip: { get_attr: [storage_backend_server_port, fixed_ips, 0, ip_address] }
             $storage_backend_network_cidr: { get_param: storage_backend_network_cidr }
 
+  inject_files:
+    type: "OS::Heat::CloudConfig"
+    properties:
+      cloud_config:
+        write_files:
+          - path: /usr/sbin/prepare-metadata.py
+            owner: "root:root"
+            permissions: "0755"
+            content: {get_file: ../scripts/prepare-metadata.py}
+          - path: /usr/share/metadata/lab-metadata.yaml
+            owner: "root:root"
+            permissions: "0644"
+            content: { get_param: hardware_metadata}
+
+  install_config_agent:
+    type: "OS::Heat::MultipartMime"
+    properties:
+      parts:
+      - config: {get_resource: software_config}
+      - config: {get_resource: inject_files}
+
   server:
     type: OS::Nova::Server
     properties:
@@ -103,8 +127,8 @@
         - network: { get_param: accessible_network }
         # NOTE(ohryhorov): connect to accessible network only as ironic doesn't
         # support multitenancy use-case. Use private_floating_network for IPAM only.
-      user_data_format: RAW
-      user_data: { get_resource: software_config }
+      user_data_format: SOFTWARE_CONFIG
+      user_data: { get_resource:  install_config_agent}
       metadata: { get_param: metadata }
 
   private_floating_server_port:
@@ -150,3 +174,6 @@
   server_public_ip:
     description: Floating IP address of server in public network
     value: { get_attr: [server, networks, { get_param: accessible_network}, 0]}
+  wc_data:
+    description: Metadata from instance
+    value: { get_attr: [wait_condition, data]}
diff --git a/de/heat-templates/fragments/SrvInstancesVM.yaml b/de/heat-templates/fragments/SrvInstancesVM.yaml
index 5b1a681..fbedc71 100644
--- a/de/heat-templates/fragments/SrvInstancesVM.yaml
+++ b/de/heat-templates/fragments/SrvInstancesVM.yaml
@@ -45,6 +45,10 @@
     type: string
   docker_ee_url:
     type: string
+  hardware_metadata:
+    description: The content of lab metadata.
+    default: ''
+    type: string
 
 resources:
 
@@ -69,6 +73,27 @@
             $private_floating_network_cidr: { get_param: private_floating_network_cidr }
             $functions_override: { get_param: functions_override }
 
+  inject_files:
+    type: "OS::Heat::CloudConfig"
+    properties:
+      cloud_config:
+        write_files:
+          - path: /usr/sbin/prepare-metadata.py
+            owner: "root:root"
+            permissions: "0755"
+            content: {get_file: ../scripts/prepare-metadata.py}
+          - path: /usr/share/metadata/lab-metadata.yaml
+            owner: "root:root"
+            permissions: "0644"
+            content: { get_param: hardware_metadata}
+
+  install_config_agent:
+    type: "OS::Heat::MultipartMime"
+    properties:
+      parts:
+      - config: {get_resource: software_config}
+      - config: {get_resource: inject_files}
+
   server:
     type: OS::Nova::Server
     properties:
@@ -79,8 +104,8 @@
       networks:
         - port: { get_resource: accessible_server_port }
         - port: { get_resource: private_floating_server_port }
-      user_data_format: RAW
-      user_data: { get_resource: software_config }
+      user_data_format: SOFTWARE_CONFIG
+      user_data: { get_resource:  install_config_agent}
       metadata: { get_param: metadata }
 
   accessible_server_port:
@@ -123,3 +148,6 @@
   server_public_ip:
     description: Floating IP address of server in public network
     value: { get_attr: [ server_floating_ip, floating_ip_address ] }
+  wc_data:
+    description: Metadata from instance
+    value: { get_attr: [wait_condition, data]}
diff --git a/de/heat-templates/fragments/SrvInstancesVMCeph.yaml b/de/heat-templates/fragments/SrvInstancesVMCeph.yaml
index 68f937b..7d4b249 100644
--- a/de/heat-templates/fragments/SrvInstancesVMCeph.yaml
+++ b/de/heat-templates/fragments/SrvInstancesVMCeph.yaml
@@ -53,6 +53,9 @@
     type: string
   docker_ee_url:
     type: string
+  hardware_metadata:
+    description: The content of lab metadata.
+    type: string
 
 resources:
 
@@ -143,3 +146,6 @@
   server_public_ip:
     description: Floating IP address of server in public network
     value: { get_attr: [ server_floating_ip, floating_ip_address ] }
+  wc_data:
+    description: Metadata from instance
+    value: { get_attr: [wait_condition, data]}
diff --git a/de/heat-templates/fragments/SrvInstancesVMCephOSD.yaml b/de/heat-templates/fragments/SrvInstancesVMCephOSD.yaml
index 0522672..cc6b89c 100644
--- a/de/heat-templates/fragments/SrvInstancesVMCephOSD.yaml
+++ b/de/heat-templates/fragments/SrvInstancesVMCephOSD.yaml
@@ -61,6 +61,9 @@
     type: string
   docker_ee_url:
     type: string
+  hardware_metadata:
+    description: The content of lab metadata.
+    type: string
 
 resources:
 
@@ -163,3 +166,6 @@
   server_public_ip:
     description: Floating IP address of server in public network
     value: { get_attr: [ server_floating_ip, floating_ip_address ] }
+  wc_data:
+    description: Metadata from instance
+    value: { get_attr: [wait_condition, data]}
diff --git a/de/heat-templates/scripts/instance_boot.sh b/de/heat-templates/scripts/instance_boot.sh
index a1928b0..0e7cde0 100644
--- a/de/heat-templates/scripts/instance_boot.sh
+++ b/de/heat-templates/scripts/instance_boot.sh
@@ -80,8 +80,9 @@
 
 function wait_condition_send {
     local status=${1:-SUCCESS}
-    local reason=${2:-empty}
-    local data_binary="{\"status\": \"$status\", \"reason\": \"$reason\"}"
+    local reason=${2:-\"empty\"}
+    local data=${3:-empty}
+    local data_binary="{\"status\": \"$status\", \"reason\": \"$reason\", \"data\": $data}"
     echo "Trying to send signal to wait condition 5 times: $data_binary"
     WAIT_CONDITION_NOTIFY_EXIT_CODE=2
     i=0
@@ -315,8 +316,21 @@
     retry 10 "Labeling node failed" set_node_labels_retry
 }
 
+HW_METADATA=''
+# Place files specified in metadata to system.
+# For example netplan.io metadata, the restart of services
+# is not covered by script.
+function prepare_metadata_files {
+    /usr/sbin/prepare-metadata.py  --metadata-file /usr/share/metadata/lab-metadata.yaml
+    if [[ -f /usr/share/metadata/ceph.yaml ]]; then
+        HW_METADATA="{\"ceph\": {\"$(hostname)\": \"$(base64 -w 0 /usr/share/metadata/ceph.yaml)\"}}"
+    fi
+}
+
+
 case "$NODE_TYPE" in
     ucp)
+        prepare_metadata_files
         prepare_network
         update_docker_network
         install_required_packages
@@ -333,6 +347,7 @@
         set_node_labels
         ;;
     master)
+        prepare_metadata_files
         prepare_network
         update_docker_network
         install_required_packages
@@ -346,6 +361,7 @@
         set_node_labels
         ;;
     worker)
+        prepare_metadata_files
         prepare_network
         update_docker_network
         install_required_packages
@@ -364,4 +380,4 @@
 esac
 
 
-wait_condition_send "SUCCESS" "Instance successfuly started."
+wait_condition_send "SUCCESS" "Instance successfuly started." "${HW_METADATA}"
diff --git a/de/heat-templates/scripts/prepare-metadata.py b/de/heat-templates/scripts/prepare-metadata.py
new file mode 100644
index 0000000..93c4cf5
--- /dev/null
+++ b/de/heat-templates/scripts/prepare-metadata.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python3
+#
+# Copyright 2018 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+
+"""Prepare metadata python module
+
+The module is aimed to prepare system files files (networking configs etc)
+based on lab metadata.
+
+Example:
+  python prepare-metadata --metadata-file '/etc/lab-metadata.yaml'
+
+Example of lab-metadata.yaml
+
+'52:54:00:10:94:78':
+  write_files:
+  - path: '/tmp/123.yaml'
+    content: |
+      foo: bar
+
+Attributes:
+  metadata-file - The file with metadata
+"""
+
+
+__version__ = '1.0'
+
+import argparse
+import os
+import yaml
+import logging
+import netifaces
+import sys
+
+LOG = logging.getLogger(__name__)
+
+
+def main():
+    logging.basicConfig(
+        format='%(asctime)s - %(levelname)s - %(message)s'
+    )
+    LOG.setLevel(logging.INFO)
+
+    parser = argparse.ArgumentParser(
+        description=('Render system files based on metadata')
+    )
+
+    group = parser.add_argument_group()
+    group.add_argument(
+        '--metadata-file',
+        help='The path to metadata file.',
+        required=True
+    )
+    args = parser.parse_args()
+
+    with open(args.metadata_file) as f:
+        metadata = yaml.safe_load(f)
+    node_meta = get_node_metadata(metadata)
+    if node_meta is not None:
+        LOG.info(f"Processing node_metadata: {node_meta}")
+        create_files(node_meta.get('write_files', []))
+    else:
+        LOG.error("No matches to MACs for node_metadata found")
+
+def get_interface_mac(iface_name):
+    mac = None
+    ifaddresses = netifaces.ifaddresses(iface_name)
+    link = ifaddresses.get(netifaces.AF_LINK, [])
+    if link:
+        return link[0]['addr']
+
+def get_node_macs():
+    ifaces = netifaces.interfaces()
+    macs = [get_interface_mac(iface_name) for iface_name in ifaces]
+    return [mac for mac in macs if mac is not None]
+
+def get_node_metadata(metadata):
+    for mac in get_node_macs():
+        if mac in metadata:
+             return metadata[mac]
+
+def create_files(files_meta):
+    for file_meta in files_meta:
+        path = file_meta['path']
+        content = file_meta['content']
+        permissions = int(str(file_meta.get('permissions', '644')), base=8)
+        with open(path, "w") as f:
+            f.write(content)
+        os.chmod(path, permissions)
+
+if __name__ == '__main__':
+    try:
+        main()
+    except Exception as e:
+        LOG.exception(f"Failed to apply image layout: {e}")
+        sys.exit(1)
diff --git a/de/heat-templates/top.yaml b/de/heat-templates/top.yaml
index 957243e..ff01525 100644
--- a/de/heat-templates/top.yaml
+++ b/de/heat-templates/top.yaml
@@ -142,6 +142,10 @@
   metallb_address_pools:
     type: comma_delimited_list
     default: ''
+  hardware_metadata:
+    description: The content of lab metadata.
+    default: ''
+    type: string
 
 resources:
   key_pair:
@@ -191,6 +195,7 @@
       public_net_id: { get_param: public_net_id }
       host_interface: { get_param: host_interface }
       functions_override: { get_param: functions_override }
+      hardware_metadata: { get_param: hardware_metadata}
 
   masters:
     type: OS::Heat::ResourceGroup
@@ -218,6 +223,7 @@
           host_interface: { get_param: host_interface }
           ucp_master_host: { get_attr: [ucp, server_private_ip] }
           functions_override: { get_param: functions_override }
+          hardware_metadata: { get_param: hardware_metadata}
 
   workers:
     type: OS::Heat::ResourceGroup
@@ -250,6 +256,7 @@
           storage_frontend_network: { get_attr: [storage_network, storage_frontend_network_id] }
           storage_frontend_subnet_id: { get_attr: [storage_network, storage_frontend_subnet_id] }
           storage_frontend_network_cidr: { get_param: storage_frontend_network_cidr }
+          hardware_metadata: { get_param: hardware_metadata}
 
   cmps:
     type: OS::Heat::ResourceGroup
@@ -281,6 +288,7 @@
           storage_frontend_network: { get_attr: [storage_network, storage_frontend_network_id] }
           storage_frontend_subnet_id: { get_attr: [storage_network, storage_frontend_subnet_id] }
           storage_frontend_network_cidr: { get_param: storage_frontend_network_cidr }
+          hardware_metadata: { get_param: hardware_metadata}
 
   gtws:
     type: OS::Heat::ResourceGroup
@@ -308,6 +316,7 @@
           host_interface: { get_param: host_interface }
           ucp_master_host: { get_attr: [ucp, server_private_ip] }
           functions_override: { get_param: functions_override }
+          hardware_metadata: { get_param: hardware_metadata}
 
   lmas:
     type: OS::Heat::ResourceGroup
@@ -339,6 +348,7 @@
           storage_frontend_network: { get_attr: [storage_network, storage_frontend_network_id] }
           storage_frontend_subnet_id: { get_attr: [storage_network, storage_frontend_subnet_id] }
           storage_frontend_network_cidr: { get_param: storage_frontend_network_cidr }
+          hardware_metadata: { get_param: hardware_metadata}
 
   osds:
     type: OS::Heat::ResourceGroup
@@ -374,6 +384,7 @@
           storage_backend_network: { get_attr: [storage_network, storage_backend_network_id] }
           storage_backend_subnet_id: { get_attr: [storage_network, storage_backend_subnet_id] }
           storage_backend_network_cidr: { get_param: storage_backend_network_cidr }
+          hardware_metadata: { get_param: hardware_metadata}
 
   ntws:
     type: OS::Heat::ResourceGroup
@@ -401,6 +412,7 @@
           host_interface: { get_param: host_interface }
           ucp_master_host: { get_attr: [ucp, server_private_ip] }
           functions_override: { get_param: functions_override }
+          hardware_metadata: { get_param: hardware_metadata}
 
 outputs:
   ucp_ips:
@@ -444,3 +456,27 @@
     value: { get_param: live_migration_interface }
   metallb_address_pools:
     value: { get_param: metallb_address_pools }
+  ucp_wc_data:
+    description: Metadata from ucp
+    value: { get_attr: [ucp, wc_data] }
+  masters_wc_data:
+    description: Metadata from masters
+    value: { get_attr: [masters, wc_data] }
+  workers_wc_data:
+    description: Metadata from workers
+    value: { get_attr: [workers, wc_data] }
+  cmps_wc_data:
+    description: Metadata from cmps
+    value: { get_attr: [cmps, wc_data] }
+  gtws_wc_data:
+    description: Metadata from gtws
+    value: { get_attr: [gtws, wc_data] }
+  lmas_wc_data:
+    description: Metadata from lmas
+    value: { get_attr: [lmas, wc_data] }
+  osds_wc_data:
+    description: Metadata from osds
+    value: { get_attr: [osds, wc_data] }
+  ntws_wc_data:
+    description: Metadata from ntws
+    value: { get_attr: [ntws, wc_data] }
diff --git a/tox.ini b/tox.ini
index 13a82ae..a229dc4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -23,6 +23,7 @@
          -not -name \*.rej                       \
          -not -name \*.yaml                      \
          -not -name \*.lic                       \
+         -not -name \*.py                        \
          \(                                      \
           -name \*.sh -or                        \
           -wholename \*/de/\*                    \