"Fossies" - the Fresh Open Source Software Archive

Member "ansible-2.9.27/contrib/inventory/abiquo.py" (11 Oct 2021, 8847 Bytes) of package /linux/misc/ansible-2.9.27.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "abiquo.py" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.9.24_vs_4.3.0.

    1 #!/usr/bin/env python
    2 # -*- coding: utf-8 -*-
    3 
    4 '''
    5 External inventory script for Abiquo
    6 ====================================
    7 
    8 Shamelessly copied from an existing inventory script.
    9 
   10 This script generates an inventory that Ansible can understand by making API requests to Abiquo API
   11 Requires some python libraries, ensure to have them installed when using this script.
   12 
   13 This script has been tested in Abiquo 3.0 but it may work also for Abiquo 2.6.
   14 
   15 Before using this script you may want to modify abiquo.ini config file.
   16 
   17 This script generates an Ansible hosts file with these host groups:
   18 
   19 ABQ_xxx: Defines a hosts itself by Abiquo VM name label
   20 all: Contains all hosts defined in Abiquo user's enterprise
   21 virtualdatecenter: Creates a host group for each virtualdatacenter containing all hosts defined on it
   22 virtualappliance: Creates a host group for each virtualappliance containing all hosts defined on it
   23 imagetemplate: Creates a host group for each image template containing all hosts using it
   24 
   25 '''
   26 
   27 # (c) 2014, Daniel Beneyto <daniel.beneyto@abiquo.com>
   28 #
   29 # This file is part of Ansible,
   30 #
   31 # Ansible is free software: you can redistribute it and/or modify
   32 # it under the terms of the GNU General Public License as published by
   33 # the Free Software Foundation, either version 3 of the License, or
   34 # (at your option) any later version.
   35 #
   36 # Ansible is distributed in the hope that it will be useful,
   37 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   38 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39 # GNU General Public License for more details.
   40 #
   41 # You should have received a copy of the GNU General Public License
   42 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
   43 
   44 import os
   45 import sys
   46 import time
   47 
   48 import json
   49 
   50 from ansible.module_utils.six.moves import configparser as ConfigParser
   51 from ansible.module_utils.urls import open_url
   52 
   53 
   54 def api_get(link, config):
   55     try:
   56         if link is None:
   57             url = config.get('api', 'uri') + config.get('api', 'login_path')
   58             headers = {"Accept": config.get('api', 'login_type')}
   59         else:
   60             url = link['href'] + '?limit=0'
   61             headers = {"Accept": link['type']}
   62         result = open_url(url, headers=headers, url_username=config.get('auth', 'apiuser').replace('\n', ''),
   63                           url_password=config.get('auth', 'apipass').replace('\n', ''))
   64         return json.loads(result.read())
   65     except Exception:
   66         return None
   67 
   68 
   69 def save_cache(data, config):
   70     ''' saves item to cache '''
   71     dpath = config.get('cache', 'cache_dir')
   72     try:
   73         cache = open('/'.join([dpath, 'inventory']), 'w')
   74         cache.write(json.dumps(data))
   75         cache.close()
   76     except IOError as e:
   77         pass  # not really sure what to do here
   78 
   79 
   80 def get_cache(cache_item, config):
   81     ''' returns cached item  '''
   82     dpath = config.get('cache', 'cache_dir')
   83     inv = {}
   84     try:
   85         cache = open('/'.join([dpath, 'inventory']), 'r')
   86         inv = cache.read()
   87         cache.close()
   88     except IOError as e:
   89         pass  # not really sure what to do here
   90 
   91     return inv
   92 
   93 
   94 def cache_available(config):
   95     ''' checks if we have a 'fresh' cache available for item requested '''
   96 
   97     if config.has_option('cache', 'cache_dir'):
   98         dpath = config.get('cache', 'cache_dir')
   99 
  100         try:
  101             existing = os.stat('/'.join([dpath, 'inventory']))
  102         except Exception:
  103             # cache doesn't exist or isn't accessible
  104             return False
  105 
  106         if config.has_option('cache', 'cache_max_age'):
  107             maxage = config.get('cache', 'cache_max_age')
  108             if (int(time.time()) - int(existing.st_mtime)) <= int(maxage):
  109                 return True
  110 
  111     return False
  112 
  113 
  114 def generate_inv_from_api(enterprise_entity, config):
  115     try:
  116         inventory['all'] = {}
  117         inventory['all']['children'] = []
  118         inventory['all']['hosts'] = []
  119         inventory['_meta'] = {}
  120         inventory['_meta']['hostvars'] = {}
  121 
  122         enterprise = api_get(enterprise_entity, config)
  123         vms_entity = next(link for link in enterprise['links'] if link['rel'] == 'virtualmachines')
  124         vms = api_get(vms_entity, config)
  125         for vmcollection in vms['collection']:
  126             for link in vmcollection['links']:
  127                 if link['rel'] == 'virtualappliance':
  128                     vm_vapp = link['title'].replace('[', '').replace(']', '').replace(' ', '_')
  129                 elif link['rel'] == 'virtualdatacenter':
  130                     vm_vdc = link['title'].replace('[', '').replace(']', '').replace(' ', '_')
  131                 elif link['rel'] == 'virtualmachinetemplate':
  132                     vm_template = link['title'].replace('[', '').replace(']', '').replace(' ', '_')
  133 
  134             # From abiquo.ini: Only adding to inventory VMs with public IP
  135             if config.getboolean('defaults', 'public_ip_only') is True:
  136                 for link in vmcollection['links']:
  137                     if link['type'] == 'application/vnd.abiquo.publicip+json' and link['rel'] == 'ip':
  138                         vm_nic = link['title']
  139                         break
  140                     else:
  141                         vm_nic = None
  142             # Otherwise, assigning defined network interface IP address
  143             else:
  144                 for link in vmcollection['links']:
  145                     if link['rel'] == config.get('defaults', 'default_net_interface'):
  146                         vm_nic = link['title']
  147                         break
  148                     else:
  149                         vm_nic = None
  150 
  151             vm_state = True
  152             # From abiquo.ini: Only adding to inventory VMs deployed
  153             if config.getboolean('defaults', 'deployed_only') is True and vmcollection['state'] == 'NOT_ALLOCATED':
  154                 vm_state = False
  155 
  156             if vm_nic is not None and vm_state:
  157                 if vm_vapp not in inventory:
  158                     inventory[vm_vapp] = {}
  159                     inventory[vm_vapp]['children'] = []
  160                     inventory[vm_vapp]['hosts'] = []
  161                 if vm_vdc not in inventory:
  162                     inventory[vm_vdc] = {}
  163                     inventory[vm_vdc]['hosts'] = []
  164                     inventory[vm_vdc]['children'] = []
  165                 if vm_template not in inventory:
  166                     inventory[vm_template] = {}
  167                     inventory[vm_template]['children'] = []
  168                     inventory[vm_template]['hosts'] = []
  169                 if config.getboolean('defaults', 'get_metadata') is True:
  170                     meta_entity = next(link for link in vmcollection['links'] if link['rel'] == 'metadata')
  171                     try:
  172                         metadata = api_get(meta_entity, config)
  173                         if (config.getfloat("api", "version") >= 3.0):
  174                             vm_metadata = metadata['metadata']
  175                         else:
  176                             vm_metadata = metadata['metadata']['metadata']
  177                         inventory['_meta']['hostvars'][vm_nic] = vm_metadata
  178                     except Exception as e:
  179                         pass
  180 
  181                 inventory[vm_vapp]['children'].append(vmcollection['name'])
  182                 inventory[vm_vdc]['children'].append(vmcollection['name'])
  183                 inventory[vm_template]['children'].append(vmcollection['name'])
  184                 inventory['all']['children'].append(vmcollection['name'])
  185                 inventory[vmcollection['name']] = []
  186                 inventory[vmcollection['name']].append(vm_nic)
  187 
  188         return inventory
  189     except Exception as e:
  190         # Return empty hosts output
  191         return {'all': {'hosts': []}, '_meta': {'hostvars': {}}}
  192 
  193 
  194 def get_inventory(enterprise, config):
  195     ''' Reads the inventory from cache or Abiquo api '''
  196 
  197     if cache_available(config):
  198         inv = get_cache('inventory', config)
  199     else:
  200         default_group = os.path.basename(sys.argv[0]).rstrip('.py')
  201         # MAKE ABIQUO API CALLS #
  202         inv = generate_inv_from_api(enterprise, config)
  203 
  204     save_cache(inv, config)
  205     return json.dumps(inv)
  206 
  207 
  208 if __name__ == '__main__':
  209     inventory = {}
  210     enterprise = {}
  211 
  212     # Read config
  213     config = ConfigParser.SafeConfigParser()
  214     for configfilename in [os.path.abspath(sys.argv[0]).rstrip('.py') + '.ini', 'abiquo.ini']:
  215         if os.path.exists(configfilename):
  216             config.read(configfilename)
  217             break
  218 
  219     try:
  220         login = api_get(None, config)
  221         enterprise = next(link for link in login['links'] if link['rel'] == 'enterprise')
  222     except Exception as e:
  223         enterprise = None
  224 
  225     if cache_available(config):
  226         inventory = get_cache('inventory', config)
  227     else:
  228         inventory = get_inventory(enterprise, config)
  229 
  230     # return to ansible
  231     sys.stdout.write(str(inventory))
  232     sys.stdout.flush()