Abr 01 2021
Inventario dinámico Ansible de Servidores IBM Cloud
IBM Cloud se basa en la API Softlayer – también conocida como IBM Classic Infrastructure – para automatizar acciones. La API está disponible en diferentes lenguajes como Python, Go, Java o PHP.
Voy a generar un inventario dinámico de los servidores recuperados de mi cuenta de IBM Cloud directamente utilizables por Ansible.
Generaré grupos correspondientes a los datacenters. También le gustaría agrupar servidores en todo tipo de categorías como bases de datos, Mysql, Linux, Web, etc… No se preocupe, también podemos hacer esto de una forma muy sencilla.
Esto se puede lograr agregando etiquetas a los hosts en IBM Cloud portal y obviamente, un host puede tener varias etiquetas y pertenecer a los grupos de Ansible correspondientes a estas etiquetas / tags.
Una vez que estos grupos han sido declarados en el archivo inventory, puede ejecutar playbooks de Ansible como instalar paquetes de Apache en servidores que pertenecen al grupo «Web» por ejemplo.
Primero debe agregar su API key en un archivo de shell para ejecutar antes del script. Podría ser parte del script, pero permite que cada usuario use su propia clave.
export SL_USERNAME=nombre_usuario
export SL_API_KEY=a1b2c3[...]3456
Ejecute . ./IBM_SL_env.sh primero para agregar el nombre de usuario y la clave de API en las variables de entorno que leerá el script de Python a continuación.
#!/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())
Algunas notas:
Los nodos de Kubernetes administrado son visibles en la infraestructura clásica de IBM Cloud como cualquier VM (VSI en terminología de IBM) pero no puede conectarse a ellos. Por lo tanto, se agregan a la categoría «Kube» antes de ser ignorados.
Se crea un archivo separado en hosts_var para cada servidor, que contiene su dirección IP. Puede agregar otras variables como parámetros iSCSI, etc…
El script recupera máquinas virtuales en el inventario Ansible, así como máquinas físicas (bare metal). Es posible comentar cualquiera de estas secciones si no es necesario, guardando una llamada a IBM.