{"id":1021,"date":"2021-04-01T07:21:35","date_gmt":"2021-04-01T05:21:35","guid":{"rendered":"http:\/\/www.netexpertise.eu\/en\/?p=1021"},"modified":"2021-08-10T07:53:26","modified_gmt":"2021-08-10T05:53:26","slug":"build-ansible-inventory-from-ibm-cloud-resources","status":"publish","type":"post","link":"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html","title":{"rendered":"Build Ansible Inventory from IBM Cloud Resources"},"content":{"rendered":"\n<p>IBM Cloud relies on <a href=\"https:\/\/sldn.softlayer.com\/article\/getting-started\/\">Softlayer API<\/a> &#8211; also called IBM Classic Infrastructure &#8211; to automate things. The API is available in different languages such as Python, Go, Java or PHP, and can be used to build an Ansible inventory.<br><br><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img decoding=\"async\" src=\"\/uploads\/duck-meet-ducks-rubber-ducks-3325701.jpg\" alt=\"\"\/><figcaption><a href=\"https:\/\/pixabay.com\/users\/manfredrichter\">manfredrichter<\/a> \/ Pixabay<\/figcaption><\/figure><\/div>\n\n\n\n<p>Here I will generate automatically a host inventory collected from my IBM Cloud account, directly usable by <a href=\"\/en\/category\/devops\/ansible\">Ansible<\/a>. I will also generate datacenters groups. You may want to fit servers in all kinds of categories such as Databases, Mysql, Linux, Web, etc&#8230; No worries, we can do that too in a really simple way.<br>This can be achieved adding tags to hosts on <a href=\"http:\/\/cloud.ibm.com\">IBM Cloud portal<\/a> and a host can indeed have multiple tags and belongs to Ansible groups matching these tags.<\/p>\n\n\n\n<p>Once these groups are declared in the inventory file, you can apply Ansible playbooks like Install Apache package on servers that belong to the &#8220;Web&#8221; hostgroup for instance.<\/p>\n\n\n\n<p><br>You first need to add your API key into a shell file you will execute before running the script. It could be in the script, but this allows each user to have his own key in a separate file. The API Key can be generated or found on <a href=\"https:\/\/cloud.ibm.com\" target=\"_blank\" rel=\"noreferrer noopener\">IBM Cloud portal<\/a>.<br><br><\/p>\n\n\n\n<pre title=\"IBM_SL_env.sh\" class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">export SL_USERNAME=username\nexport SL_API_KEY=a1b2c3[...]3456<\/code><\/pre>\n\n\n\n<p><br>Run <em>. .\/IBM_SL_env.sh<\/em> first to set username and API key into environment variables that will be used by the following Python script.<br><br><\/p>\n\n\n\n<pre title=\"IBM_cloud_inventory.py\" class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#!\/usr\/bin\/env python3 &nbsp;\nimport os\nimport SoftLayer\n \nHOST_VARS_DIR&nbsp; = \"host_vars\"\nINVENTORY_FILE = \"inventory\"\n \nclass Inventory:\n &nbsp; def __init__(self):\n &nbsp; &nbsp; &nbsp;# Variables\n &nbsp; &nbsp; &nbsp;self.categories = {}\n &nbsp; &nbsp; &nbsp;self.datacenter = {}\n &nbsp; &nbsp; &nbsp;self.servers = {}\n \n &nbsp; &nbsp; &nbsp;# Create Softlayer connection\n &nbsp; &nbsp; &nbsp;self.client = SoftLayer.create_client_from_env()\n \n &nbsp; &nbsp; &nbsp;# Init Methods\n &nbsp; &nbsp; &nbsp;self.get_server_list()\n &nbsp; &nbsp; &nbsp;self.write_inventory()\n \n\n &nbsp; def short_host_name(self, host):\n &nbsp; &nbsp; &nbsp;return host['fullyQualifiedDomainName'][:host['fullyQualifiedDomainName'].find('.mydomain.')]\n \n\n &nbsp; def add_host_to_cat(self, host, cat):\n &nbsp; &nbsp; &nbsp;if cat == \"ibm-kubernetes-service\": cat = \"kube\"\n &nbsp; &nbsp; &nbsp;if cat not in self.categories:\n &nbsp; &nbsp; &nbsp; &nbsp; self.categories[cat] = [host]\n &nbsp; &nbsp; &nbsp;else:\n &nbsp; &nbsp; &nbsp; &nbsp; self.categories[cat].append(host)\n \n\n &nbsp; def add_server_to_list(self, host):\n &nbsp; &nbsp; &nbsp;try:\n &nbsp; &nbsp; &nbsp; &nbsp; host[\"primaryBackendIpAddress\"]\n &nbsp; &nbsp; &nbsp;except KeyError:\n &nbsp; &nbsp; &nbsp; &nbsp; pass\n &nbsp; &nbsp; &nbsp;else:\n &nbsp; &nbsp; &nbsp; &nbsp; host[\"ShortHostname\"] = self.short_host_name(host)\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; # Build server Categories list\n &nbsp; &nbsp; &nbsp; &nbsp; if host[\"tagReferences\"] != []:\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for tagRef in host[\"tagReferences\"]:\n &nbsp; &nbsp; &nbsp; &nbsp;       self.add_host_to_cat(host[\"ShortHostname\"], tagRef[\"tag\"][\"name\"].strip())\n &nbsp; &nbsp; &nbsp; &nbsp;  &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; # Build datacenter lists\n &nbsp; &nbsp; &nbsp; &nbsp; if host[\"datacenter\"][\"name\"] not in self.datacenter:\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.datacenter[host[\"datacenter\"][\"name\"]] = [host[\"ShortHostname\"]]\n &nbsp; &nbsp; &nbsp; &nbsp; else:\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.datacenter[host[\"datacenter\"][\"name\"]].append(host[\"ShortHostname\"])\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; # Build server attribute list\n &nbsp; &nbsp; &nbsp; &nbsp; serverAttributes = {}\n &nbsp; &nbsp; &nbsp; &nbsp; serverAttributes['IP'] = host[\"primaryBackendIpAddress\"]\n &nbsp; &nbsp; &nbsp; &nbsp; self.servers[host[\"ShortHostname\"]] = serverAttributes\n &nbsp;&nbsp; &nbsp;\n\n &nbsp; def get_server_list(self):\n &nbsp; &nbsp; &nbsp;object_mask = \"mask[id,fullyQualifiedDomainName,\" \\\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\"primaryBackendIpAddress,\" \\\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\"tagReferences[tag[name]],\" \\\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\"datacenter]\"\n \n &nbsp; &nbsp; &nbsp;# Get virtual server list\n &nbsp; &nbsp; &nbsp;mgr = SoftLayer.VSManager(self.client)\n &nbsp; &nbsp; &nbsp;for vs in mgr.list_instances(mask=object_mask):\n &nbsp; &nbsp; &nbsp; &nbsp; self.add_server_to_list(vs)\n \n &nbsp; &nbsp; &nbsp;# Get bare metal servers\n &nbsp; &nbsp; &nbsp;hsl = SoftLayer.HardwareManager(self.client)\n &nbsp; &nbsp; &nbsp;for hs in hsl.list_hardware(mask=object_mask):\n &nbsp; &nbsp; &nbsp; &nbsp; self.add_server_to_list(hs)\n \n\n &nbsp; def write_inventory(self):\n &nbsp; &nbsp; &nbsp;# host_vars structure\n &nbsp; &nbsp; &nbsp;if not os.path.exists(HOST_VARS_DIR):\n &nbsp; &nbsp; &nbsp; &nbsp; os.makedirs(HOST_VARS_DIR)\n \n &nbsp; &nbsp; &nbsp;inventoryFile = open(INVENTORY_FILE,\"w\")\n \n &nbsp; &nbsp; &nbsp;for cat in self.categories.keys():\n &nbsp; &nbsp; &nbsp; &nbsp; if cat != \"kube\":\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;inventoryFile.write(\"[\" + cat + \"]\\n\")\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for host in self.categories[cat]:\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # write host vars\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inventoryFile.write(host + \"\\n\")\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; file = open(HOST_VARS_DIR+\"\/\"+host,\"w\")\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; file.write(\"ansible_host: \" + self.servers[host]['IP'] + \"\\n\")\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; file.close() &nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;inventoryFile.write(\"\\n\")\n &nbsp; &nbsp; &nbsp;for dc in self.datacenter.keys():\n &nbsp; &nbsp; &nbsp; &nbsp; inventoryFile.write(\"[\" + dc + \"]\\n\")\n &nbsp; &nbsp; &nbsp; &nbsp; for host in self.datacenter[dc]:\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if not host.startswith(\"kube\"):\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inventoryFile.write(host + \"\\n\")\n &nbsp; &nbsp; &nbsp; &nbsp; inventoryFile.write(\"\\n\")\n &nbsp; &nbsp; &nbsp;inventoryFile.close()\n\nif __name__ == \"__main__\":\n &nbsp; exit(Inventory())<\/code><\/pre>\n\n\n\n<p><br>A few notes:<br>Managed Kubernetes nodes are visible in IBM classic infrastructure like any other VM (VSI in IBM terminology) but you cannot connect on to them. They&#8217;re added to the &#8220;Kube&#8221; category before being ignored.<\/p>\n\n\n\n<p>A distinct file is created in hosts_var for every server with its IP address. You could add more variables into it of course such as iSCSI settings, etc&#8230;<\/p>\n\n\n\n<p>The script collects virtual machines as well as bare metal machines. You can comment out one of these sections if you don&#8217;t need it, saving one call to IBM.<\/p>\n\n\n\n<p>Now you can build an Ansible inventory with IBM cloud hosts on the fly in less than 10 seconds.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>IBM Cloud relies on Softlayer API &#8211; also called IBM Classic Infrastructure &#8211; to automate things. The API is available in different languages such as Python, Go, Java or PHP, and can be used to build an Ansible inventory. Here I will generate automatically a host inventory collected from my IBM Cloud account, directly usable [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[427,431],"tags":[429,215,436,414],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.8.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Netexpertise - Build Ansible Inventory from IBM Cloud Resources<\/title>\n<meta name=\"description\" content=\"Build dynamically your Ansible inventory from IBM Cloud resources with Softlayer API in Python\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Netexpertise - Build Ansible Inventory from IBM Cloud Resources\" \/>\n<meta property=\"og:description\" content=\"Build dynamically your Ansible inventory from IBM Cloud resources with Softlayer API in Python\" \/>\n<meta property=\"og:url\" content=\"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html\" \/>\n<meta property=\"og:site_name\" content=\"Netexpertise\" \/>\n<meta property=\"article:published_time\" content=\"2021-04-01T05:21:35+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-08-10T05:53:26+00:00\" \/>\n<meta name=\"author\" content=\"dave\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@netexpertise\" \/>\n<meta name=\"twitter:site\" content=\"@netexpertise\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html\",\"url\":\"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html\",\"name\":\"Netexpertise - Build Ansible Inventory from IBM Cloud Resources\",\"isPartOf\":{\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#website\"},\"datePublished\":\"2021-04-01T05:21:35+00:00\",\"dateModified\":\"2021-08-10T05:53:26+00:00\",\"author\":{\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/cb4cd666549d22e9070ec1cfc1a496fa\"},\"description\":\"Build dynamically your Ansible inventory from IBM Cloud resources with Softlayer API in Python\",\"breadcrumb\":{\"@id\":\"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.netexpertise.eu\/en\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Build Ansible Inventory from IBM Cloud Resources\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#website\",\"url\":\"https:\/\/www.netexpertise.eu\/en\/\",\"name\":\"Netexpertise\",\"description\":\"Systems \/ Networks \/ DevOps\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.netexpertise.eu\/en\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/cb4cd666549d22e9070ec1cfc1a496fa\",\"name\":\"dave\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/image\/\",\"url\":\"http:\/\/1.gravatar.com\/avatar\/1129916e1f4955bd632f27f836f64e55?s=96&d=mm&r=g\",\"contentUrl\":\"http:\/\/1.gravatar.com\/avatar\/1129916e1f4955bd632f27f836f64e55?s=96&d=mm&r=g\",\"caption\":\"dave\"},\"sameAs\":[\"http:\/\/www.netexpertise.eu\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Netexpertise - Build Ansible Inventory from IBM Cloud Resources","description":"Build dynamically your Ansible inventory from IBM Cloud resources with Softlayer API in Python","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html","og_locale":"en_US","og_type":"article","og_title":"Netexpertise - Build Ansible Inventory from IBM Cloud Resources","og_description":"Build dynamically your Ansible inventory from IBM Cloud resources with Softlayer API in Python","og_url":"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html","og_site_name":"Netexpertise","article_published_time":"2021-04-01T05:21:35+00:00","article_modified_time":"2021-08-10T05:53:26+00:00","author":"dave","twitter_card":"summary_large_image","twitter_creator":"@netexpertise","twitter_site":"@netexpertise","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html","url":"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html","name":"Netexpertise - Build Ansible Inventory from IBM Cloud Resources","isPartOf":{"@id":"https:\/\/www.netexpertise.eu\/en\/#website"},"datePublished":"2021-04-01T05:21:35+00:00","dateModified":"2021-08-10T05:53:26+00:00","author":{"@id":"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/cb4cd666549d22e9070ec1cfc1a496fa"},"description":"Build dynamically your Ansible inventory from IBM Cloud resources with Softlayer API in Python","breadcrumb":{"@id":"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html"]}]},{"@type":"BreadcrumbList","@id":"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/build-ansible-inventory-from-ibm-cloud-resources.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.netexpertise.eu\/en"},{"@type":"ListItem","position":2,"name":"Build Ansible Inventory from IBM Cloud Resources"}]},{"@type":"WebSite","@id":"https:\/\/www.netexpertise.eu\/en\/#website","url":"https:\/\/www.netexpertise.eu\/en\/","name":"Netexpertise","description":"Systems \/ Networks \/ DevOps","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.netexpertise.eu\/en\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/cb4cd666549d22e9070ec1cfc1a496fa","name":"dave","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/image\/","url":"http:\/\/1.gravatar.com\/avatar\/1129916e1f4955bd632f27f836f64e55?s=96&d=mm&r=g","contentUrl":"http:\/\/1.gravatar.com\/avatar\/1129916e1f4955bd632f27f836f64e55?s=96&d=mm&r=g","caption":"dave"},"sameAs":["http:\/\/www.netexpertise.eu"]}]}},"_links":{"self":[{"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/posts\/1021"}],"collection":[{"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/comments?post=1021"}],"version-history":[{"count":0,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/posts\/1021\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/media?parent=1021"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/categories?post=1021"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/tags?post=1021"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}