Add ability to pass hardware metadata

Related-Prod: PRODX-00000
Change-Id: I4c377558ffe13e28f8ac5ced45262ff67556f46c
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)