Avr 01 2021

Inventaire Ansible Dynamique des Serveurs IBM Cloud

Publié par à 6:24 sous Ansible,Python

IBM Cloud repose sur l’API Softlayer – aussi appelée IBM Classic Infrastructure – pour automatiser les actions. L’API est disponible en différents langages comme Python, Go, Java ou PHP et nous permettra de générer un inventaire Ansible.


Je vais générer un inventaire dynamique des serveurs récupérés sur mon compte IBM Cloud directement utilisable par Ansible. Je vais aussi générer des groupes correspondants aux datacenters. Vous aimeriez aussi regrouper les serveurs dans toutes sortes de catégories comme Databases, Mysql, Linux, Web, etc… Pas d’inquiétude, on peut aussi faire ca de façon très simple.
On peut y parvenir en ajoutant des tags aux hosts dans le portail IBM Cloud et un host peut avoir plusieurs tags évidemment et appartenir aux groupes Ansible correspondants à ces tags/étiquettes.

Une fois que ces groupes ont été déclarés dans le fichier inventory, vous pouvez lancer les playbooks Ansible comme l’installation des paquets Apache sur les serveurs appartenant au groupe « Web » par exemple.


Vous devez d’abord ajouter votre API key dans un fichier shell à exécuter avant de lancer le script. Ca pourrait faire partie du script, mais cella permet à chaque utilisateur d’utiliser sa propre clé. La clé d’API peut être générée ou trouvée sur le portail IBM Cloud.

export SL_USERNAME=nom_utilisateur
export SL_API_KEY=a1b2c3[...]3456


Lancez . ./IBM_SL_env.sh tout d’abord pour ajouter le username et l’API key dans des variables d’environnement qui seront lues par le script Python ci-dessous.

#!/usr/bin/env python3  
import os
import SoftLayer
 
HOST_VARS_DIR  = "host_vars"
INVENTORY_FILE = "inventory"
 
class Inventory:
   def __init__(self):
      # Variables
      self.categories = {}
      self.datacenter = {}
      self.servers = {}
 
      # Create Softlayer connection
      self.client = SoftLayer.create_client_from_env()
 
      # Init Methods
      self.get_server_list()
      self.write_inventory()
 

   def short_host_name(self, host):
      return host['fullyQualifiedDomainName'][:host['fullyQualifiedDomainName'].find('.mydomain.')]
 

   def add_host_to_cat(self, host, cat):
      if cat == "ibm-kubernetes-service": cat = "kube"
      if cat not in self.categories:
         self.categories[cat] = [host]
      else:
         self.categories[cat].append(host)
 

   def add_server_to_list(self, host):
      try:
         host["primaryBackendIpAddress"]
      except KeyError:
         pass
      else:
         host["ShortHostname"] = self.short_host_name(host)
             
         # Build server Categories list
         if host["tagReferences"] != []:
            for tagRef in host["tagReferences"]:
               self.add_host_to_cat(host["ShortHostname"], tagRef["tag"]["name"].strip())
             
         # Build datacenter lists
         if host["datacenter"]["name"] not in self.datacenter:
            self.datacenter[host["datacenter"]["name"]] = [host["ShortHostname"]]
         else:
            self.datacenter[host["datacenter"]["name"]].append(host["ShortHostname"])
             
         # Build server attribute list
         serverAttributes = {}
         serverAttributes['IP'] = host["primaryBackendIpAddress"]
         self.servers[host["ShortHostname"]] = serverAttributes
     

   def get_server_list(self):
      object_mask = "mask[id,fullyQualifiedDomainName," \
                    "primaryBackendIpAddress," \
                    "tagReferences[tag[name]]," \
                    "datacenter]"
 
      # Get virtual server list
      mgr = SoftLayer.VSManager(self.client)
      for vs in mgr.list_instances(mask=object_mask):
         self.add_server_to_list(vs)
 
      # Get bare metal servers
      hsl = SoftLayer.HardwareManager(self.client)
      for hs in hsl.list_hardware(mask=object_mask):
         self.add_server_to_list(hs)
 

   def write_inventory(self):
      # host_vars structure
      if not os.path.exists(HOST_VARS_DIR):
         os.makedirs(HOST_VARS_DIR)
 
      inventoryFile = open(INVENTORY_FILE,"w")
 
      for cat in self.categories.keys():
         if cat != "kube":
            inventoryFile.write("[" + cat + "]\n")
            for host in self.categories[cat]:
               # write host vars
               inventoryFile.write(host + "\n")
               file = open(HOST_VARS_DIR+"/"+host,"w")
               file.write("ansible_host: " + self.servers[host]['IP'] + "\n")
               file.close()        
            inventoryFile.write("\n")
      for dc in self.datacenter.keys():
         inventoryFile.write("[" + dc + "]\n")
         for host in self.datacenter[dc]:
            if not host.startswith("kube"):
               inventoryFile.write(host + "\n")
         inventoryFile.write("\n")
      inventoryFile.close()

if __name__ == "__main__":
   exit(Inventory())


Quelques notes:

Les nodes Kubernetes managés sont visibles dans l’infrastructure classique d’IBM comme n’importe quelle VM (VSI dans la terminologie IBM) mais vous ne pouvez pas vous y connecter. Ils sont donc ajoutés à la catégorie « Kube » avant d’être ignorés.


Un fichier distinct est créé dans hosts_var pour chaque serveur contenant son address IP. Vous pourriez y ajouter d’autres variables comme les paramètres iSCSI, etc…


Le script récupère les machines virtuelles ainsi que les machines physique bare metal. Vous pouvez commenter l’une de ces sections si vous n’en avez pas besoin, épargnant un appel à IBM.


No responses yet

Comments RSS

Leave a Reply