9711600e64d143301bce819dd6242e5bba0fa7c1 — Louis Solofrizzo 16 days ago 80b505e
scripts: Update dyn.py

Signed-off-by: Louis Solofrizzo <lsolofrizzo@online.net>
1 files changed, 203 insertions(+), 22 deletions(-)

M scripts/dyn.py
M scripts/dyn.py => scripts/dyn.py +203 -22
@@ 2,9 2,12 @@   import sys
  import yaml
+ import yamlordereddictloader
  import json
  import os
  import argparse
+ import copy
+ import jinja2
  
  parser = argparse.ArgumentParser()
  parser.add_argument('--hosts', action='store_true')


@@ 13,32 16,146 @@ parser.add_argument('--dns', action='store_true')
  args = parser.parse_args()
  
+ def jinjaize(element, vars_dict):
+     if isinstance(element, dict):
+         for key in element:
+             element[key] = jinjaize(element[key], vars_dict)
+     elif isinstance(element, list):
+         for idx in range(len(element)):
+             element[idx] = jinjaize(element[idx], vars_dict)
+     elif isinstance(element, str):
+         element = jinja2.Template(element, undefined=jinja2.StrictUndefined).render(vars_dict)
+     return element
+ 
+ def merge(a, b, path=None):
+     "merges b into a"
+     if path is None: path = []
+     for key in b:
+         if key in a:
+             if isinstance(a[key], dict) and isinstance(b[key], dict):
+                 a[key] = merge(a[key], b[key], path + [str(key)])
+             elif a[key] == b[key]:
+                 pass # same leaf value
+             elif type(a[key]) == type(b[key]):
+                 a[key] = b[key]
+             else:
+                 raise Exception('Conflict at %s' % '.'.join(path + [str(key)]))
+         else:
+             a[key] = b[key]
+     return a
+ 
  # check arguments
  if not (args.hosts or args.dns or args.list or args.host):
      parser.error('There are no actions. You must use --hosts or --dns or --list or --host')
  
- def read_machines(inventory, machines, result, product_name, env):
-     if "machines" not in inventory:
-         return
+ def read_machines_v1(inventory, machines, result, product_name, env):
+     global_vars = {}
+     for region, d in inventory['machines'].items():
+         if region == "vars":
+             global_vars = d
+             continue
+         for az, d in d.items():
+             if az == "vars":
+                 merge(global_vars, d)
+                 continue
+             for platform, d in d.items():
+                 if platform == "vars":
+                     merge(global_vars, d)
+                     continue
+                 for cluster, d in d.items():
+                     if cluster == "vars":
+                         merge(global_vars, d)
+                         continue
+                     for subcluster, d in d.items():
+                         if subcluster == "vars":
+                             merge(global_vars, d)
+                             continue
+                         for machine_type, d in d.items():
+                             if machine_type == "vars":
+                                 merge(global_vars, d)
+                                 continue
+                             count = 1
+                             for key, d in d.items():
+                                 if key == "vars":
+                                     merge(global_vars, d)
+                                     continue
+                                 name = "%(region)s%(az)s-%(platform)s%(cluster)s%(subcluster)s-%(machine_type)s%(id)s" % { "region": region, "az": az, "platform": platform, "cluster": cluster, "subcluster": str(subcluster).zfill(2), "machine_type": machine_type, "id": str(key).zfill(2) }
+                                 machines[name] = {
+                                     'hostname': name,
+                                     'ansible_ssh_host': d['net']['adm']['ipv4']
+                                 }
+ 
+                                 for key, d in d.items():
+                                     if key == "ipv4":
+                                         continue
+                                     machines[name][key] = d
+ 
+                                 if machine_type not in result:
+                                     result[machine_type] = {'hosts': []}
+                                 result[machine_type]['hosts'].append(name)
+ 
+                                 if machine_type not in result['all']['children']:
+                                     result['all']['children'].append(machine_type)
+ 
+                                 result['all']['vars']['hosts'][name] = machines[name]
+                                 merge(result['all']['vars']['hosts'][name], global_vars)
+ 
+ def read_machines_v2(inventory, machines, result, product_name, env):
+     global_vars = {}
+     _vars = {
+         'region': {},
+         'az': {},
+         'dc': {},
+         'cluster': {},
+         'type': {},
+         'machine': {},
+     }
  
      for region, d in inventory['machines'].items():
+         if region == "vars":
+             _vars['region'] = d
+             continue
+ 
+         _vars['az'] = copy.deepcopy(_vars['region'])
          for az, d in d.items():
+             if az == "vars":
+                 merge(_vars['az'], d)
+                 continue
+ 
+             _vars['dc'] = copy.deepcopy(_vars['az'])
              for datacenter, d in d.items():
+                 if datacenter == "vars":
+                     merge(_vars['dc'], d)
+                     continue
+ 
+                 _vars['cluster'] = copy.deepcopy(_vars['dc'])
                  for cluster, d in d.items():
+                     if cluster == "vars":
+                         merge(_vars['cluster'], d)
+                         continue
+ 
+                     _vars['type'] = copy.deepcopy(_vars['cluster'])
                      for machine_type, d in d.items():
+                         if machine_type == "vars":
+                             merge(_vars['type'], d)
+                             continue
+ 
                          count = 1
-                         for ip in d:
+                         _vars['machine'] = copy.deepcopy(_vars['type'])
+                         for key, d in d.items():
+                             if key == "vars":
+                                 merge(_vars['machine'], d)
+                                 continue
+ 
+                             machine_vars = copy.deepcopy(_vars['machine'])
                              name = region + str(az) + datacenter + "-" + product_name + \
-                             "-" + env + "-" + cluster + machine_type + str(count).zfill(2)
+                             "-" + env + "-" + cluster + machine_type + str(key).zfill(2)
                              machines[name] = {
-                                 'ipv4': ip['ipv4'],
                                  'hostname': name,
+                                 'ansible_ssh_host': d['net']['adm']['ipv4']
                              }
  
-                             for key, item in ip.items():
-                                 if key == "ipv4":
-                                     continue
-                                 machines[name][key] = item
+                             merge(machine_vars, d)
  
                              if machine_type not in result:
                                  result[machine_type] = {'hosts': []}


@@ 47,29 164,68 @@ if machine_type not in result['all']['children']:
                                  result['all']['children'].append(machine_type)
  
+                             if "group" in machine_vars:
+                                 if machine_vars["group"] not in result:
+                                     result[machine_vars["group"]] = {'hosts': []}
+                                 result[machine_vars["group"]]['hosts'].append(name)
+ 
+                                 if machine_vars["group"] not in result['all']['children']:
+                                     result['all']['children'].append(machine_vars["group"])
+ 
                              result['all']['vars']['hosts'][name] = machines[name]
+                             result['all']['vars']['hosts'][name] = merge(result['all']['vars']['hosts'][name], machine_vars)
+ 
+ 
+ def read_machines(inventory, machines, result, product_name, env):
+     if "schemaver" in inventory:
+         schemaver = inventory["schemaver"]
+     else:
+         print("No schemaver exiting")
+         sys.exit(1)
+ 
+     if "includes" in inventory:
+         for include in inventory['includes']:
+             include_ext_inv(machines, result, include)
+ 
+     if "vars" in inventory:
+         for k, v in inventory["vars"].items():
+             result['all']['vars'][k] = v
+ 
+     if "machines" not in inventory:
+         return
+ 
+     if schemaver == "v1":
+         read_machines_v1(inventory, machines, result, product_name, env)
+     elif schemaver == "v2":
+         read_machines_v2(inventory, machines, result, product_name, env)
+     else:
+         print("Unsupported Schemaver %s exiting" % schemaver)
  
-                             count = count + 1
  
  def include_ext_inv(machines, result, path):
-     with open(os.getenv("SRC_DIR") + '/'+ path +'/inventory.yml', 'r') as f:
+     with open(os.getenv("SRC_DIR") + '/'+ path +'.yml', 'r') as f:
          try:
-             inventory = yaml.load(f)
+             inventory = yaml.load(f, Loader=yamlordereddictloader.Loader)
          except yaml.YAMLError as exc:
              print(exc)
              sys.exit(1)
  
          product_name = inventory['name']
          if "environment" not in inventory:
-             env = path.split("/")[-1]
+             env = path.split("/")[-2]
          else:
              env = inventory["environment"]
  
          read_machines(inventory, machines, result, product_name, env)
  
- with open('inventory.yml', 'r') as f:
+ scope = os.getenv("SCOPE")
+ if not scope:
+     print("No Scope specified aborting !")
+     sys.exit(1)
+ 
+ with open(scope + '.yml', 'r') as f:
      try:
-         inventory = yaml.load(f)
+         inventory = yaml.load(f, Loader=yamlordereddictloader.Loader)
      except yaml.YAMLError as exc:
          print(exc)
          sys.exit(1)


@@ 89,12 245,13 @@ result = {
          'all': {
              'children': [],
-             'vars': inventory['vars'] if "vars" in inventory else {}
+             'vars': {}
          }
      }
  
      result['all']['vars']['hosts'] = {}
      result['all']['vars']['product_name'] = product_name
+     result['all']['vars']['env'] = env
  
      # Default to root user for SSH if none was specified
      if "ansible_ssh_user" not in result['all']['vars']:


@@ 102,20 259,44 @@       read_machines(inventory, machines, result, product_name, env)
  
-     if "includes" in inventory:
-         for include in inventory['includes']:
-             include_ext_inv(machines, result, include)
+     # We are building a squashfs image
+     if "PXE_SELECTOR" in os.environ:
+         name = os.environ["PXE_SELECTOR"]
+         to_append = []
+ 
+         # Include the PXE inventory
+         include_ext_inv(machines, result, "pxe/deploy/prd/fr-par")
+ 
+         for machine in result['pxebuilder']['hosts']:
+             # Replace the name of the machine and append the desired selector
+             pxe_tmp_name = machine + "-" + name
+             machines[pxe_tmp_name] = machines[machine].copy()
+             machines[pxe_tmp_name]['ansible_ssh_port'] = machines[machine]['chroot_ssh_port']
+             machines[pxe_tmp_name]['hostname'] = pxe_tmp_name
+             result['all']['vars']['hosts'][pxe_tmp_name] = machines[pxe_tmp_name]
+             to_append.append(pxe_tmp_name)
+ 
+         # Empty the PXE machines
+         result['pxebuilder']['hosts'] = []
+         result['all']['vars']['env'] = "pxe"
+ 
+         # Add the 'fakes' pxe hosts
+         for name in to_append:
+             result['pxebuilder']['hosts'].append(name)
  
+     result = jinjaize(result, result['all']['vars'])
      if len(sys.argv) == 1:
          print("Need at least one option")
          sys.exit(1)
  
      if args.hosts:
          for key, machine in machines.items():
-             print(machine['ipv4'] + "\t" + key)
+             print(machine['net']['adm']['ipv4'] + "\t" + key)
      elif args.dns:
          for key, machine in machines.items():
-             print(key +" IN A "+ machine['ipv4'])
+             print(key +" IN A "+ machine['net']['adm']['ipv4'])
+             if 'ipmi' in machine['net']:
+                 print(key +".ipmi IN A "+ machine['net']['adm']['ipv4'])
      elif args.list:
          print(json.dumps(result, indent=4))
      elif args.host: