4e0d893d70a11389da37b5404366d1ef816b60d1
[pharos.git] / config / utils / generate_config.py
1 #!/usr/bin/python
2 ##############################################################################
3 # Copyright (c) 2017 OPNFV and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ##############################################################################
10 """This module does blah blah."""
11 import argparse
12 import ipaddress
13 import logging
14 import os
15 import yaml
16 from jinja2 import Environment, FileSystemLoader
17 from subprocess import CalledProcessError, check_output
18
19 PARSER = argparse.ArgumentParser()
20 PARSER.add_argument("--yaml", "-y", type=str, required=True)
21 PARSER.add_argument("--jinja2", "-j", type=str, required=True)
22 ARGS = PARSER.parse_args()
23
24 # Processor architecture vs DPKG architecture mapping
25 DPKG_ARCH_TABLE = {
26     'aarch64': 'arm64',
27     'x86_64': 'amd64',
28 }
29 ARCH_DPKG_TABLE = dict(zip(DPKG_ARCH_TABLE.values(), DPKG_ARCH_TABLE.keys()))
30
31 # Custom filter to allow simple IP address operations returning
32 # a new address from an upper or lower (negative) index
33 def ipaddr_index(base_address, index):
34     """Return IP address in given network at given index"""
35     try:
36         base_address_str = unicode(base_address)
37     #pylint: disable=unused-variable
38     except NameError as ex:
39         base_address_str = str(base_address)
40     return ipaddress.ip_address(base_address_str) + int(index)
41
42 # Custom filter to transform a prefix netmask to IP address format netmask
43 def netmask(prefix):
44     """Get netmask from prefix length integer"""
45     try:
46         prefix_str = unicode(prefix)
47     except NameError as ex:
48         prefix_str = str(prefix)
49     return ipaddress.IPv4Network("1.0.0.0/"+prefix_str).netmask
50
51 # Custom filter to convert between processor architecture
52 # (as reported by $(uname -m)) and DPKG-style architecture
53 def dpkg_arch(arch, to_dpkg=True):
54     """Return DPKG-compatible from processor arch and vice-versa"""
55     if to_dpkg:
56         return DPKG_ARCH_TABLE[arch]
57     else:
58         return ARCH_DPKG_TABLE[arch]
59
60 ENV = Environment(loader=FileSystemLoader(os.path.dirname(ARGS.jinja2)))
61 ENV.filters['ipaddr_index'] = ipaddr_index
62 ENV.filters['netmask'] = netmask
63 ENV.filters['dpkg_arch'] = dpkg_arch
64
65 # Run `eyaml decrypt` on the whole file, but only if PDF data is encrypted
66 # Note: eyaml return code is 0 even if keys are not available
67 try:
68     if 'ENC[PKCS7' in open(ARGS.yaml).read():
69         DICT = yaml.safe_load(check_output(['eyaml', 'decrypt',
70                                             '-f', ARGS.yaml]))
71 except CalledProcessError as ex:
72     logging.error('eyaml decryption failed! Fallback to raw data.')
73 except OSError as ex:
74     logging.warn('eyaml not found, skipping decryption. Fallback to raw data.')
75 try:
76     DICT['details']
77 except (NameError, TypeError) as ex:
78     with open(ARGS.yaml) as _:
79         DICT = yaml.safe_load(_)
80
81 # If an installer descriptor file (IDF) exists, include it (temporary)
82 IDF_PATH = '/idf-'.join(os.path.split(ARGS.yaml))
83 if os.path.exists(IDF_PATH):
84     with open(IDF_PATH) as _:
85         IDF = yaml.safe_load(_)
86         DICT['idf'] = IDF['idf']
87
88 # Print dictionary generated from yaml (uncomment for debug)
89 # print(DICT)
90
91 # Render template and print generated conf to console
92 TEMPLATE = ENV.get_template(os.path.basename(ARGS.jinja2))
93
94 #pylint: disable=superfluous-parens
95 print(TEMPLATE.render(conf=DICT))