Skip to content

Instantly share code, notes, and snippets.

@mccbryan3
Last active February 25, 2020 12:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mccbryan3/fbde13e8100cd96aee4480158053daaf to your computer and use it in GitHub Desktop.
Save mccbryan3/fbde13e8100cd96aee4480158053daaf to your computer and use it in GitHub Desktop.
Dynamic inventory script for Ansible using the OME API to find device Type of 1000
#!/usr/bin/env python
# Copyright: (c) 2018, Keiran Steele
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
import os
import sys
import argparse
try:
import requests
except ImportError:
sys.exit('requests package is required for this inventory script')
try:
import json
except ImportError:
import simplejson as json
inline_config = {
"config_vars" : {
"base_host_url" : None,
"base_api_url" : "/api/DeviceService/Devices?$top=1000",
"username" : None, #Only put your username here for testing purposes
"password" : None, #Only put your password here for testing purposes
},
"group_by" : {
"Model"
},
"hosts_vars" : {
"ip" : {
"ansible_ssh_host" : "NetworkAddress"
},
"general" : {
"model" : "Model",
"service_tag" : "DeviceServiceTag"
}
}
}
def cli_arguments():
"""
Script cli arguments
Ansible calls "--list" as an argument by default
"""
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--list", help="Print all hosts with vars as Ansible dynamic inventory syntax.",
action="store_true")
parser.add_argument("--host", help="Print specific host vars as Ansible dynamic inventory syntax.",
action="store")
arguments = parser.parse_args()
return arguments
class OpenManageInventory(object):
def __init__(self, script_args, config):
"""
Define and populate attributes from either environment variables or inline configuation data
"""
self.list = script_args.list
self.host = script_args.host
if os.environ.get('OM_USERNAME'):
self.username = os.environ.get('OM_USERNAME')
elif config['config_vars']['username']:
self.username = config['config_vars']['username']
else:
raise ValueError('No Username Provided')
if os.environ.get('OM_PASSWORD'):
self.password = os.environ.get('OM_PASSWORD')
elif config['config_vars']['password']:
self.username = config['config_vars']['password']
else:
raise ValueError('No Password Provided')
if os.environ.get('OM_HOSTURL'):
self.host_url = os.environ.get('OM_HOSTURL')
elif config['config_vars']['base_host_url']:
self.host_url = config['config_vars']['base_host_url']
else:
raise ValueError('No URL provided for the OpenManage host')
if config['config_vars']['base_api_url']:
self.base_api_url = config['config_vars']['base_api_url']
else:
raise ValueError('No API URL provided.')
if config['group_by']:
self.group_by = config['group_by']
else:
self.group_by = {}
if config['hosts_vars']:
self.hosts_vars = config['hosts_vars']
else:
self.hosts_vars = {}
def get_devices_list(self, host_url, base_api_url, username, password):
"""
Calls the Dell OME API for a list of devices and their associated data
Returns:
hosts_list
"""
api_url = host_url + base_api_url
hosts_list = []
while api_url:
# Get hosts list
r = requests.get(api_url, auth=(username, password), verify=False)
r.raise_for_status()
api_output = r.json()
api_output_data = api_output["value"]
if isinstance(api_output, dict) and "value" in api_output:
hosts_list += api_output_data
try:
nextpage = api_output["@odata.nextLink"]
except:
nextpage = None
api_url = None
if nextpage != None:
api_url = host_url + nextpage
return hosts_list
@staticmethod
def add_host_to_group(server_name, group_value, inventory_dict):
"""
Add a host to a single group
"""
group_name = group_value
if server_name and group_value:
if group_name not in inventory_dict:
inventory_dict.update({group_name: []})
#if server_name not in inventory_dict[group_name]:
inventory_dict[group_name].append(server_name)
return inventory_dict
def add_host_to_inventory(self, groups, inventory_dict, host_data):
"""
Add host to the inventory dict and put in the ungrouped group if no other group is provided.
If a group is provided and the group value exists in the host data, the host will be put in that group.
Returns:
Updated inventory dict
"""
server_name = host_data.get("DeviceName")
if groups:
for group in groups:
if host_data:
group_value = host_data[group]
if group_value:
self.add_host_to_group(server_name, group_value, inventory_dict)
else:
self._put_host_to_ungrouped(inventory_dict, server_name)
else:
self._put_host_to_ungrouped(inventory_dict, server_name)
return inventory_dict
@staticmethod
def _put_host_to_ungrouped(inventory_dict, server_name):
"""
Add host to the "ungrouped" group
"""
if "ungrouped" not in inventory_dict:
inventory_dict.setdefault("ungrouped", [server_name])
else:
if server_name not in inventory_dict["ungrouped"]:
inventory_dict["ungrouped"].append(server_name)
def get_host_vars(self, host_data, host_vars):
"""
Iterate through host_vars and add variables to the host_vars_dict based on the source for each category.
Returns:
Dictionary of vars for host.
"""
host_vars_dict = dict()
if host_vars:
# categories_source indicates which part of of the host_data dict to get vars from
categories_source = {
"ip" : host_data['DeviceManagement'][0],
"general" : host_data
}
for category in host_vars:
data_dict = categories_source[category]
for var_name, var_data in host_vars[category].items():
var_value = data_dict.get(var_data)
if var_value is not None:
host_vars_dict.update({var_name: var_value})
return host_vars_dict
def update_host_meta_vars(self, inventory_dict, host_name, host_vars):
"""
Updates inventory dict with host vars
Returns:
Updated Inventory dict
"""
if host_vars and not self.host:
inventory_dict['_meta']['hostvars'].update({host_name: host_vars})
elif host_vars and self.host:
inventory_dict.update({host_name: host_vars})
return inventory_dict
def generate_inventory(self):
"""
Generate the dynamic inventory for Ansible
Returns:
A dict object with the Ansible inventory of hosts and their vars.
"""
inventory_dict = dict()
openmanage_devices_list = self.get_devices_list(self.host_url, self.base_api_url, self.username, self.password)
if openmanage_devices_list:
inventory_dict.update({"_meta": {"hostvars": {}}})
for current_host in openmanage_devices_list:
server_name = current_host.get("DeviceName")
server_type = current_host.get("Type")
if server_type == 1000:
self.add_host_to_inventory(self.group_by, inventory_dict, current_host)
host_vars = self.get_host_vars(current_host, self.hosts_vars)
inventory_dict = self.update_host_meta_vars(inventory_dict, server_name, host_vars)
return inventory_dict
def print_inventory_json(self, inventory_dict):
"""
Print Inventory.
"""
if self.host:
result = inventory_dict.setdefault(self.host, {})
elif self.list:
result = inventory_dict
else:
result = {}
print(json.dumps(result))
# Main
def main():
args = cli_arguments()
#config_data = get_config_data(inline_config)
openmanage = OpenManageInventory(args, inline_config)
ansible_inventory = openmanage.generate_inventory()
openmanage.print_inventory_json(ansible_inventory)
# Run main
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment