Server IP : 85.214.239.14 / Your IP : 3.147.74.197 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /proc/3/root/proc/2/task/2/root/proc/2/task/2/root/lib/python3/dist-packages/ansible_collections/ngine_io/cloudstack/plugins/inventory/ |
Upload File : |
# -*- coding: utf-8 -*- # # Copyright (c) 2020, Rafael del valle <rafael@privaz.io> # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = r''' name: instance short_description: Apache CloudStack instance inventory source author: Rafael del Valle (@rvalle) version_added: 2.1.0 description: - Get inventory hosts from Apache CloudStack - Allows filtering and grouping inventory hosts. - | Uses an YAML configuration file ending with either I(cloudstack-instances.yml) or I(cloudstack-instances.yaml) to set parameter values (also see examples). options: plugin: description: Token that ensures this is a source file for the 'instance' plugin. type: string required: True choices: [ ngine_io.cloudstack.instance ] hostname: description: | Field to match the hostname. Note v4_main_ip corresponds to the primary ipv4address of the first nic adapter of the instance. type: string default: v4_default_ip choices: - v4_default_ip - hostname filter_by_zone: description: Only return instances in the provided zone. type: string filter_by_domain: description: Only return instances in the provided domain. type: string filter_by_project: description: Only return instances in the provided project. type: string filter_by_vpc: description: Only return instances in the provided VPC. type: string extends_documentation_fragment: - constructed - ngine_io.cloudstack.cloudstack - ngine_io.cloudstack.cloudstack_environment ''' # TODO: plugin should work as 'cloudstack' only EXAMPLES = ''' # inventory_cloudstack.yml file in YAML format # Example command line: ansible-inventory --list -i cloudstack-instances.yml plugin: ngine_io.cloudstack.instance # Use the default ip as ansible_host hostname: v4_default_ip # Return only instances related to the VPC vpc1 and in the zone EU filter_by_vpc: vpc1 filter_by_zone: EU # Group instances with a disk_offering as storage # Create a group dmz for instances connected to the dmz network groups: storage: disk_offering is defined dmz: "'dmz' in networks" # Group the instances by network, with net_network1 as name of the groups # Group the instanes by custom tag sla, groups like sla_value for tag sla keyed_groups: - prefix: net key: networks - prefix: sla key: tags.sla ''' # The J2 Template takes 'instance' object as returned from ACS and returns 'instance' object as returned by # This inventory plugin. # The data structure of this inventory has been designed according to the following criteria: # - do not duplicate/compete with Ansible instance facts # - do not duplicate/compete with Cloudstack facts modules # - hide internal ACS structures and identifiers # - if possible use similar naming to previous inventory script # - prefer non-existing attributes over null values # - populate the data required to group and filter instances INVENTORY_NORMALIZATION_J2 = ''' --- instance: name: {{ instance.name }} hostname: {{ instance.hostname or instance.name | lower }} v4_default_ip: {{ instance.nic[0].ipaddress }} zone: {{ instance.zonename }} domain: {{ instance.domain | lower }} account: {{ instance.account }} username: {{ instance.username }} {% if instance.group %} group: {{ instance.group }} {% endif %} {% if instance.tags %} tags: {% for tag in instance.tags %} {{ tag.key }}: {{ tag.value }} {% endfor %} {% endif %} template: {{ instance.templatename }} service_offering: {{ instance.serviceofferingname }} {% if instance.diskofferingname is defined %} disk_offering: {{ instance.diskofferingname }} {% endif %} {% if instance.affinitygroup %} affinity_groups: {% for ag in instance.affinitygroup %} - {{ ag.name }} {% endfor %} {% endif %} networks: {% for nic in instance.nic %} - {{ nic.networkname }} {% endfor %} ha_enabled: {{ instance.haenable }} password_enabled: {{ instance.passwordenabled }} hypervisor: {{ instance.hypervisor | lower }} cpu_speed: {{ instance.cpuspeed }} cpu_number: {{ instance.cpunumber }} memory: {{ instance.memory }} dynamically_scalable: {{ instance.isdynamicallyscalable }} state: {{ instance.state }} cpu_usage: {{ instance.cpuused }} created: {{ instance.created }} ''' import yaml from ansible.module_utils.basic import missing_required_lib from ansible.plugins.inventory import (AnsibleError, BaseInventoryPlugin, Constructable) from jinja2 import Template from ..module_utils.cloudstack import HAS_LIB_CS try: from cs import CloudStack, CloudStackException except ImportError: pass class InventoryModule(BaseInventoryPlugin, Constructable): NAME = 'ngine_io.cloudstack.instance' def __init__(self): super().__init__() if not HAS_LIB_CS: raise AnsibleError(missing_required_lib('cs')) self._cs = None self._normalization_template = Template(INVENTORY_NORMALIZATION_J2) def init_cs(self): # The configuration logic matches modules specification api_config = { 'endpoint': self.get_option('api_url'), 'key': self.get_option('api_key'), 'secret': self.get_option('api_secret'), 'timeout': self.get_option('api_timeout'), 'method': self.get_option('api_http_method'), 'verify': self.get_option('api_verify_ssl_cert') } self._cs = CloudStack(**api_config) @property def cs(self): return self._cs def query_api(self, command, **args): res = getattr(self.cs, command)(**args) if 'errortext' in res: raise AnsibleError(res['errortext']) return res def verify_file(self, path): """return true/false if this is possibly a valid file for this plugin to consume""" valid = False if super(InventoryModule, self).verify_file(path): # base class verifies that file exists and is readable by current user if path.endswith(('cloudstack-instances.yaml', 'cloudstack-instances.yml')): valid = True return valid def add_filter(self, args, filter_option, query, arg): # is there a value to filter by? we will search with it search = self.get_option('filter_by_' + filter_option) if search: found = False # we return all items related to the query involved in the filtering result = self.query_api(query, listItems=True) for item in result[filter_option]: # if we find the searched value as either an id or a name if search in [item['id'], item['name']]: # we add the corresponding filter as query argument args[arg] = item['id'] found = True if not found: raise AnsibleError( "Could not apply filter_by_{fo}. No {fo} with id or name {s} found".format( fo=filter_option, s=search ) ) return args def get_filters(self): # Filtering as supported by ACS goes here args = { 'fetch_list': True } self.add_filter(args, 'domain', 'listDomains', 'domainid') self.add_filter(args, 'project', 'listProjects', 'projectid') self.add_filter(args, 'zone', 'listZones', 'zoneid') self.add_filter(args, 'vpc', 'listVPCs', 'vpcid') return args def normalize_instance_data(self, instance): inventory_instance_str = self._normalization_template.render(instance=instance) inventory_instance = yaml.load(inventory_instance_str, Loader=yaml.FullLoader) return inventory_instance['instance'] def parse(self, inventory, loader, path, cache=False): # call base method to ensure properties are available for use with other helper methods super(InventoryModule, self).parse(inventory, loader, path, cache) # This is the inventory Config self._read_config_data(path) # We Initialize the query_api self.init_cs() # All Hosts from self.inventory.add_group('cloudstack') # The ansible_host preference hostname_preference = self.get_option('hostname') # Retrieve the filtered list of instances instances = self.query_api('listVirtualMachines', **self.get_filters()) for instance in instances: # we normalize the instance data using the embedded J2 template instance = self.normalize_instance_data(instance) inventory_name = instance['name'] self.inventory.add_host(inventory_name, group='cloudstack') for attribute, value in instance.items(): # Add all available attributes self.inventory.set_variable(inventory_name, attribute, value) # set hostname preference self.inventory.set_variable(inventory_name, 'ansible_host', instance[hostname_preference]) # Use constructed if applicable strict = self.get_option('strict') # Composed variables self._set_composite_vars(self.get_option('compose'), instance, inventory_name, strict=strict) # Complex groups based on jinja2 conditionals, hosts that meet the conditional are added to group self._add_host_to_composed_groups(self.get_option('groups'), instance, inventory_name, strict=strict) # Create groups based on variable values and add the corresponding hosts to it self._add_host_to_keyed_groups(self.get_option('keyed_groups'), instance, inventory_name, strict=strict)