From 5328475c0e0cbcb9f622a35b5494def4f6409bf6 Mon Sep 17 00:00:00 2001 From: Tomas Sedovic Date: Fri, 2 Jun 2017 14:17:15 +0200 Subject: Add a sample inventory for openstack provisioning --- .../openstack/sample-inventory/clouds.yaml | 5 + .../sample-inventory/group_vars/OSEv3.yml | 10 + .../openstack/sample-inventory/group_vars/all.yml | 39 ++++ .../provisioning/openstack/sample-inventory/hosts | 44 ++++ .../openstack/sample-inventory/openstack.py | 252 +++++++++++++++++++++ 5 files changed, 350 insertions(+) create mode 100644 playbooks/provisioning/openstack/sample-inventory/clouds.yaml create mode 100644 playbooks/provisioning/openstack/sample-inventory/group_vars/OSEv3.yml create mode 100644 playbooks/provisioning/openstack/sample-inventory/group_vars/all.yml create mode 100644 playbooks/provisioning/openstack/sample-inventory/hosts create mode 100755 playbooks/provisioning/openstack/sample-inventory/openstack.py (limited to 'playbooks/provisioning/openstack') diff --git a/playbooks/provisioning/openstack/sample-inventory/clouds.yaml b/playbooks/provisioning/openstack/sample-inventory/clouds.yaml new file mode 100644 index 000000000..c266426c6 --- /dev/null +++ b/playbooks/provisioning/openstack/sample-inventory/clouds.yaml @@ -0,0 +1,5 @@ +ansible: + use_hostnames: True + expand_hostvars: True + fail_on_errors: True + diff --git a/playbooks/provisioning/openstack/sample-inventory/group_vars/OSEv3.yml b/playbooks/provisioning/openstack/sample-inventory/group_vars/OSEv3.yml new file mode 100644 index 000000000..d850f88a4 --- /dev/null +++ b/playbooks/provisioning/openstack/sample-inventory/group_vars/OSEv3.yml @@ -0,0 +1,10 @@ +--- +openshift_deployment_type: openshift-enterprise +openshift_release: v3.5 +openshift_master_default_subdomain: "apps.openshift.example.com" + +# NOTE(shadower): do not remove this line, otherwise the default node labels +# won't be set up. +openshift_node_labels: "{{ openstack.metadata.node_labels }}" + +osm_default_node_selector: 'region=primary' diff --git a/playbooks/provisioning/openstack/sample-inventory/group_vars/all.yml b/playbooks/provisioning/openstack/sample-inventory/group_vars/all.yml new file mode 100644 index 000000000..50aaa573d --- /dev/null +++ b/playbooks/provisioning/openstack/sample-inventory/group_vars/all.yml @@ -0,0 +1,39 @@ +env_id: "openshift" +openstack_dns_domain: "example.com" +openstack_nameservers: ["192.168.1.1"] +openstack_ssh_public_key: "openshift" +openstack_default_image_name: "rhel73" +openstack_default_flavor: "m1.medium" +openstack_external_network_name: "public" + +openstack_num_masters: 1 +openstack_num_infra: 1 +openstack_num_nodes: 2 + +docker_volume_size: "15" + +# TODO(shadower): this is identical to `openstack_dns_domain`. +# We should make it so it's not duplicated here. +dns_domain: "example.com" + +# TODO(shadower): this is identical to `openstack_nameservers`. +# We should make it so it's not duplicated here. +public_dns_forwarder: "192.168.1.1" + +openstack_subnet_prefix: "192.168.99" + +# # Red Hat subscription +# rhsm_register: True +# rhsm_repos: +# - "rhel-7-server-rpms" +# - "rhel-7-server-ose-3.5-rpms" +# - "rhel-7-server-extras-rpms" +# - "rhel-7-fast-datapath-rpms" +# rhsm_username: '' +# rhsm_password: '' +# rhsm_pool: '' + + +# NOTE(shadower): Do not change this value. The Ansible user is currently +# hardcoded to `openshift`. +ansible_user: openshift diff --git a/playbooks/provisioning/openstack/sample-inventory/hosts b/playbooks/provisioning/openstack/sample-inventory/hosts new file mode 100644 index 000000000..5f73b60f6 --- /dev/null +++ b/playbooks/provisioning/openstack/sample-inventory/hosts @@ -0,0 +1,44 @@ +#[all:vars] +# For all group_vars, see ./group_vars/all.yml + +# Create an OSEv3 group that contains the master, nodes, etcd, and lb groups. +# The lb group lets Ansible configure HAProxy as the load balancing solution. +# Comment lb out if your load balancer is pre-configured. +[cluster_hosts:children] +OSEv3 +dns + +[OSEv3:children] +masters +nodes +etcd + +# Set variables common for all OSEv3 hosts +#[OSEv3:vars] + +# For OSEv3 normal group vars, see ./group_vars/OSEv3.yml + +# Host Groups + +[masters:children] +masters.openshift.example.com + +[etcd:children] +etcd.openshift.example.com + +[nodes:children] +masters +infra.openshift.example.com +nodes.openshift.example.com + +[infra_hosts:children] +infra.openshift.example.com + +[dns:children] +dns.openshift.example.com + +[masters.openshift.example.com] +[etcd.openshift.example.com] +[infra.openshift.example.com] +[nodes.openshift.example.com] +[dns.openshift.example.com] diff --git a/playbooks/provisioning/openstack/sample-inventory/openstack.py b/playbooks/provisioning/openstack/sample-inventory/openstack.py new file mode 100755 index 000000000..9d4886261 --- /dev/null +++ b/playbooks/provisioning/openstack/sample-inventory/openstack.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python + +# Copyright (c) 2012, Marco Vito Moscaritolo +# Copyright (c) 2013, Jesse Keating +# Copyright (c) 2015, Hewlett-Packard Development Company, L.P. +# Copyright (c) 2016, Rackspace Australia +# +# This module is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software. If not, see . + +# The OpenStack Inventory module uses os-client-config for configuration. +# https://github.com/stackforge/os-client-config +# This means it will either: +# - Respect normal OS_* environment variables like other OpenStack tools +# - Read values from a clouds.yaml file. +# If you want to configure via clouds.yaml, you can put the file in: +# - Current directory +# - ~/.config/openstack/clouds.yaml +# - /etc/openstack/clouds.yaml +# - /etc/ansible/openstack.yml +# The clouds.yaml file can contain entries for multiple clouds and multiple +# regions of those clouds. If it does, this inventory module will connect to +# all of them and present them as one contiguous inventory. +# +# See the adjacent openstack.yml file for an example config file +# There are two ansible inventory specific options that can be set in +# the inventory section. +# expand_hostvars controls whether or not the inventory will make extra API +# calls to fill out additional information about each server +# use_hostnames changes the behavior from registering every host with its UUID +# and making a group of its hostname to only doing this if the +# hostname in question has more than one server +# fail_on_errors causes the inventory to fail and return no hosts if one cloud +# has failed (for example, bad credentials or being offline). +# When set to False, the inventory will return hosts from +# whichever other clouds it can contact. (Default: True) + +import argparse +import collections +import os +import sys +import time +from distutils.version import StrictVersion + +try: + import json +except: + import simplejson as json + +import os_client_config +import shade +import shade.inventory + +CONFIG_FILES = ['/etc/ansible/openstack.yaml', '/etc/ansible/openstack.yml'] + + +def get_groups_from_server(server_vars, namegroup=True): + groups = [] + + region = server_vars['region'] + cloud = server_vars['cloud'] + metadata = server_vars.get('metadata', {}) + + # Create a group for the cloud + groups.append(cloud) + + # Create a group on region + groups.append(region) + + # And one by cloud_region + groups.append("%s_%s" % (cloud, region)) + + # Check if group metadata key in servers' metadata + if 'group' in metadata: + groups.append(metadata['group']) + + for extra_group in metadata.get('groups', '').split(','): + if extra_group: + groups.append(extra_group.strip()) + + groups.append('instance-%s' % server_vars['id']) + if namegroup: + groups.append(server_vars['name']) + + for key in ('flavor', 'image'): + if 'name' in server_vars[key]: + groups.append('%s-%s' % (key, server_vars[key]['name'])) + + for key, value in iter(metadata.items()): + groups.append('meta-%s_%s' % (key, value)) + + az = server_vars.get('az', None) + if az: + # Make groups for az, region_az and cloud_region_az + groups.append(az) + groups.append('%s_%s' % (region, az)) + groups.append('%s_%s_%s' % (cloud, region, az)) + return groups + + +def get_host_groups(inventory, refresh=False): + (cache_file, cache_expiration_time) = get_cache_settings() + if is_cache_stale(cache_file, cache_expiration_time, refresh=refresh): + groups = to_json(get_host_groups_from_cloud(inventory)) + open(cache_file, 'w').write(groups) + else: + groups = open(cache_file, 'r').read() + return groups + + +def append_hostvars(hostvars, groups, key, server, namegroup=False): + hostvars[key] = dict( + ansible_ssh_host=server['interface_ip'], + openshift_hostname=server['name'], + openshift_public_hostname=server['name'], + openstack=server) + for group in get_groups_from_server(server, namegroup=namegroup): + groups[group].append(key) + + +def get_host_groups_from_cloud(inventory): + groups = collections.defaultdict(list) + firstpass = collections.defaultdict(list) + hostvars = {} + list_args = {} + if hasattr(inventory, 'extra_config'): + use_hostnames = inventory.extra_config['use_hostnames'] + list_args['expand'] = inventory.extra_config['expand_hostvars'] + if StrictVersion(shade.__version__) >= StrictVersion("1.6.0"): + list_args['fail_on_cloud_config'] = \ + inventory.extra_config['fail_on_errors'] + else: + use_hostnames = False + + for server in inventory.list_hosts(**list_args): + + if 'interface_ip' not in server: + continue + try: + if server["metadata"][os.environ['OS_INV_FILTER_KEY']] == os.environ['OS_INV_FILTER_VALUE']: + firstpass[server['name']].append(server) + except: + firstpass[server['name']].append(server) + for name, servers in firstpass.items(): + if len(servers) == 1 and use_hostnames: + append_hostvars(hostvars, groups, name, servers[0]) + else: + server_ids = set() + # Trap for duplicate results + for server in servers: + server_ids.add(server['id']) + if len(server_ids) == 1 and use_hostnames: + append_hostvars(hostvars, groups, name, servers[0]) + else: + for server in servers: + append_hostvars( + hostvars, groups, server['id'], server, + namegroup=True) + groups['_meta'] = {'hostvars': hostvars} + return groups + + +def is_cache_stale(cache_file, cache_expiration_time, refresh=False): + ''' Determines if cache file has expired, or if it is still valid ''' + if refresh: + return True + if os.path.isfile(cache_file) and os.path.getsize(cache_file) > 0: + mod_time = os.path.getmtime(cache_file) + current_time = time.time() + if (mod_time + cache_expiration_time) > current_time: + return False + return True + + +def get_cache_settings(): + config = os_client_config.config.OpenStackConfig( + config_files=os_client_config.config.CONFIG_FILES + CONFIG_FILES) + # For inventory-wide caching + cache_expiration_time = config.get_cache_expiration_time() + cache_path = config.get_cache_path() + if not os.path.exists(cache_path): + os.makedirs(cache_path) + cache_file = os.path.join(cache_path, 'ansible-inventory.cache') + return (cache_file, cache_expiration_time) + + +def to_json(in_dict): + return json.dumps(in_dict, sort_keys=True, indent=2) + + +def parse_args(): + parser = argparse.ArgumentParser(description='OpenStack Inventory Module') + parser.add_argument('--private', + action='store_true', + help='Use private address for ansible host') + parser.add_argument('--refresh', action='store_true', + help='Refresh cached information') + parser.add_argument('--debug', action='store_true', default=False, + help='Enable debug output') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('--list', action='store_true', + help='List active servers') + group.add_argument('--host', help='List details about the specific host') + + return parser.parse_args() + + +def main(): + args = parse_args() + try: + config_files = os_client_config.config.CONFIG_FILES + CONFIG_FILES + shade.simple_logging(debug=args.debug) + inventory_args = dict( + refresh=args.refresh, + config_files=config_files, + private=args.private, + ) + if hasattr(shade.inventory.OpenStackInventory, 'extra_config'): + inventory_args.update(dict( + config_key='ansible', + config_defaults={ + 'use_hostnames': False, + 'expand_hostvars': True, + 'fail_on_errors': True, + } + )) + + inventory = shade.inventory.OpenStackInventory(**inventory_args) + + if args.list: + output = get_host_groups(inventory, refresh=args.refresh) + elif args.host: + output = to_json(inventory.get_host(args.host)) + print(output) + except shade.OpenStackCloudException as e: + sys.stderr.write('%s\n' % e.message) + sys.exit(1) + sys.exit(0) + + +if __name__ == '__main__': + main() -- cgit v1.2.3