Merge "Adds Qinling Ansible role"

This commit is contained in:
Zuul 2019-06-03 20:29:41 +00:00 committed by Gerrit Code Review
commit 2208b0214e
41 changed files with 760 additions and 0 deletions

@ -69,6 +69,7 @@ Kolla-Ansible deploys containers for the following OpenStack projects:
- `Nova <https://docs.openstack.org/nova/latest/>`__
- `Octavia <https://docs.openstack.org/octavia/latest/>`__
- `Panko <https://docs.openstack.org/panko/latest/>`__
- `Qinling <https://docs.openstack.org/qinling/latest/>`__
- `Rally <https://docs.openstack.org/rally/latest/>`__
- `Sahara <https://docs.openstack.org/sahara/latest/>`__
- `Searchlight <https://docs.openstack.org/searchlight/latest/>`__

@ -375,6 +375,8 @@ prometheus_elasticsearch_exporter_port: "9108"
qdrouterd_port: "31459"
qinling_api_port: "7070"
rabbitmq_port: "5672"
rabbitmq_management_port: "15672"
rabbitmq_cluster_port: "25672"
@ -561,6 +563,7 @@ enable_horizon_murano: "{{ enable_murano | bool }}"
enable_horizon_neutron_lbaas: "{{ enable_neutron_lbaas | bool }}"
enable_horizon_neutron_vpnaas: "{{ enable_neutron_vpnaas | bool }}"
enable_horizon_octavia: "{{ enable_octavia | bool }}"
enable_horizon_qinling: "{{ enable_qinling | bool }}"
enable_horizon_sahara: "{{ enable_sahara | bool }}"
enable_horizon_searchlight: "{{ enable_searchlight | bool }}"
enable_horizon_senlin: "{{ enable_senlin | bool }}"
@ -615,6 +618,7 @@ enable_osprofiler: "no"
enable_panko: "no"
enable_placement: "{{ enable_nova }}"
enable_qdrouterd: "{{ 'yes' if om_rpc_transport == 'amqp' else 'no' }}"
enable_qinling: "no"
enable_rally: "no"
enable_redis: "no"
enable_sahara: "no"
@ -894,6 +898,12 @@ octavia_amp_boot_network_list:
octavia_amp_secgroup_list:
octavia_amp_flavor_id:
#################
# Qinling options
#################
# Configure qinling-engine certificates to authenticate with Kubernetes cluster.
qinling_kubernetes_certificates: "no"
###################
# Ceph options
###################

@ -163,6 +163,9 @@ monitoring
[magnum:children]
control
[qinling:children]
control
[sahara:children]
control
@ -508,6 +511,13 @@ magnum
[magnum-conductor:children]
magnum
# Qinling
[qinling-api:children]
qinling
[qinling-engine:children]
qinling
# Solum
[solum-api:children]
solum

@ -185,6 +185,9 @@ control
[magnum:children]
control
[qinling:children]
control
[sahara:children]
control
@ -517,6 +520,13 @@ magnum
[magnum-conductor:children]
magnum
# Qinling
[qinling-api:children]
qinling
[qinling-engine:children]
qinling
# Sahara
[sahara-api:children]
sahara

@ -286,6 +286,7 @@
- { name: "opendaylight", enabled: "{{ enable_opendaylight }}" }
- { name: "outward-rabbitmq", enabled: "{{ enable_outward_rabbitmq }}" }
- { name: "panko", enabled: "{{ enable_panko }}" }
- { name: "qinling", enabled: "{{ enable_qinling }}" }
- { name: "rabbitmq", enabled: "{{ enable_rabbitmq }}" }
- { name: "rally", enabled: "{{ enable_rally }}" }
- { name: "sahara", enabled: "{{ enable_sahara }}" }

@ -166,4 +166,9 @@
pattern ^(blazar-api|blazar-manager)$
tag openstack_python
</rule>
<rule>
key programname
pattern ^(qinling-engine|qinling-api)$
tag openstack_python
</rule>
</match>

@ -29,6 +29,7 @@
( 'nova', enable_nova ),
( 'octavia', enable_octavia ),
( 'panko', enable_panko ),
( 'qinling', enable_qinling ),
( 'rally', enable_rally ),
( 'sahara', enable_sahara ),
( 'searchlight', enable_searchlight ),

@ -0,0 +1,3 @@
"/var/log/kolla/qinling/*.log"
{
}

@ -44,6 +44,7 @@
( 'opendaylight', enable_opendaylight ),
( 'outward-rabbitmq', enable_outward_rabbitmq ),
( 'panko', enable_panko ),
( 'qinling', enable_qinling ),
( 'rabbitmq', enable_rabbitmq ),
( 'rally', enable_rally ),
( 'sahara', enable_sahara ),

@ -756,6 +756,19 @@
- haproxy_stat.find('panko_api') == -1
- "host_running_haproxy == 'None'"
- name: Checking free port for Qinling API HAProxy
wait_for:
host: "{{ kolla_internal_vip_address }}"
port: "{{ qinling_api_port }}"
connect_timeout: 1
timeout: 1
state: stopped
when:
- enable_qinling | bool
- inventory_hostname in groups['haproxy']
- haproxy_stat.find('qinling_api') == -1
- "host_running_haproxy == 'None'"
- name: Checking free port for RabbitMQ Management HAProxy
wait_for:
host: "{{ kolla_internal_vip_address }}"

@ -24,6 +24,7 @@ horizon_services:
ENABLE_NEUTRON_LBAAS: "{{ 'yes' if enable_horizon_neutron_lbaas | bool else 'no' }}"
ENABLE_NEUTRON_VPNAAS: "{{ 'yes' if enable_horizon_neutron_vpnaas | bool else 'no' }}"
ENABLE_OCTAVIA: "{{ 'yes' if enable_horizon_octavia | bool else 'no' }}"
ENABLE_QINLING: "{{ 'yes' if enable_horizon_qinling | bool else 'no' }}"
ENABLE_SAHARA: "{{ 'yes' if enable_horizon_sahara | bool else 'no' }}"
ENABLE_SEARCHLIGHT: "{{ 'yes' if enable_horizon_searchlight | bool else 'no' }}"
ENABLE_SENLIN: "{{ 'yes' if enable_horizon_senlin | bool else 'no' }}"

@ -37,6 +37,7 @@
- { name: "murano", enabled: "{{ enable_horizon_murano }}" }
- { name: "neutron", enabled: "{{ enable_neutron_horizon_policy_file }}" }
- { name: "nova", enabled: "{{ enable_nova_horizon_policy_file }}" }
- { name: "qinling", enabled: "{{ enable_horizon_qinling }}" }
- { name: "sahara", enabled: "{{ enable_horizon_sahara }}" }
- { name: "searchlight", enabled: "{{ enable_horizon_searchlight }}" }
- { name: "senlin", enabled: "{{ enable_horizon_senlin }}" }

@ -18,6 +18,7 @@
( 'murano', enable_horizon_murano ),
( 'neutron', enable_neutron ),
( 'nova', enable_nova ),
( 'qinling', enable_horizon_qinling ),
( 'sahara', enable_horizon_sahara ),
( 'searchlight', enable_horizon_searchlight ),
( 'senlin', enable_horizon_senlin ),

@ -0,0 +1,88 @@
---
project_name: "qinling"
qinling_services:
qinling-api:
container_name: qinling_api
group: qinling-api
enabled: true
image: "{{ qinling_api_image_full }}"
volumes:
- "{{ node_config_directory }}/qinling-api/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "{{ kolla_dev_repos_directory ~ '/qinling/qinling:/var/lib/kolla/venv/lib/python2.7/site-packages/qinling' if qinling_dev_mode | bool else '' }}"
- "kolla_logs:/var/log/kolla/"
dimensions: "{{ qinling_api_dimensions }}"
haproxy:
qinling_api:
enabled: "{{ enable_qinling }}"
mode: "http"
external: false
port: "{{ qinling_api_port }}"
qinling_api_external:
enabled: "{{ enable_qinling }}"
mode: "http"
external: true
port: "{{ qinling_api_port }}"
qinling-engine:
container_name: qinling_engine
group: qinling-engine
enabled: true
image: "{{ qinling_engine_image_full }}"
environment: "{{ container_proxy }}"
volumes:
- "{{ node_config_directory }}/qinling-engine/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "qinling:/var/lib/qinling/"
- "{{ kolla_dev_repos_directory ~ '/qinling/qinling:/var/lib/kolla/venv/lib/python2.7/site-packages/qinling' if qinling_dev_mode | bool else '' }}"
- "kolla_logs:/var/log/kolla/"
dimensions: "{{ qinling_engine_dimensions }}"
####################
# Database
####################
qinling_database_name: "qinling"
qinling_database_user: "{% if use_preconfigured_databases | bool and use_common_mariadb_user | bool %}{{ database_user }}{% else %}qinling{% endif %}"
qinling_database_address: "{{ database_address }}:{{ database_port }}"
####################
# Docker
####################
qinling_install_type: "{{ kolla_install_type }}"
qinling_tag: "{{ openstack_release }}"
qinling_api_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ qinling_install_type }}-qinling-api"
qinling_api_tag: "{{ qinling_tag }}"
qinling_api_image_full: "{{ qinling_api_image }}:{{ qinling_api_tag }}"
qinling_engine_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ qinling_install_type }}-qinling-engine"
qinling_engine_tag: "{{ qinling_tag }}"
qinling_engine_image_full: "{{ qinling_engine_image }}:{{ qinling_engine_tag }}"
qinling_api_dimensions: "{{ default_container_dimensions }}"
qinling_engine_dimensions: "{{ default_container_dimensions }}"
####################
# OpenStack
####################
qinling_admin_endpoint: "{{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ qinling_api_port }}"
qinling_internal_endpoint: "{{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ qinling_api_port }}"
qinling_public_endpoint: "{{ public_protocol }}://{{ kolla_external_fqdn }}:{{ qinling_api_port }}"
qinling_logging_debug: "{{ openstack_logging_debug }}"
qinling_keystone_user: "qinling"
openstack_qinling_auth: "{{ openstack_auth }}"
####################
# Kolla
####################
qinling_git_repository: "{{ kolla_dev_repos_git }}/{{ project_name }}"
qinling_dev_repos_pull: "{{ kolla_dev_repos_pull }}"
qinling_dev_mode: "{{ kolla_dev_mode }}"
qinling_source_version: "{{ kolla_source_version }}"

@ -0,0 +1,52 @@
---
- name: Restart qinling-api container
vars:
service_name: "qinling-api"
service: "{{ qinling_services[service_name] }}"
config_json: "{{ qinling_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}"
qinling_conf: "{{ qinling_confs.results|selectattr('item.key', 'equalto', service_name)|first }}"
policy_overwriting: "{{ qinling_policy_overwriting.results|selectattr('item.key', 'equalto', service_name)|first }}"
qinling_api_container: "{{ check_qinling_containers.results|selectattr('item.key', 'equalto', service_name)|first }}"
become: true
kolla_docker:
action: "recreate_or_restart_container"
common_options: "{{ docker_common_options }}"
name: "{{ service.container_name }}"
image: "{{ service.image }}"
volumes: "{{ service.volumes|reject('equalto', '')|list }}"
environment: "{{ service.environment }}"
dimensions: "{{ service.dimensions }}"
when:
- kolla_action != "config"
- inventory_hostname in groups[service.group]
- service.enabled | bool
- config_json.changed | bool
or qinling_conf.changed | bool
or policy_overwriting.changed | bool
or qinling_api_container.changed | bool
- name: Restart qinling-engine container
vars:
service_name: "qinling-engine"
service: "{{ qinling_services[service_name] }}"
config_json: "{{ qinling_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}"
qinling_conf: "{{ qinling_confs.results|selectattr('item.key', 'equalto', service_name)|first }}"
policy_overwriting: "{{ qinling_policy_overwriting.results|selectattr('item.key', 'equalto', service_name)|first }}"
qinling_engine_container: "{{ check_qinling_containers.results|selectattr('item.key', 'equalto', service_name)|first }}"
become: true
kolla_docker:
action: "recreate_or_restart_container"
common_options: "{{ docker_common_options }}"
name: "{{ service.container_name }}"
image: "{{ service.image }}"
volumes: "{{ service.volumes|reject('equalto', '')|list }}"
environment: "{{ service.environment }}"
dimensions: "{{ service.dimensions }}"
when:
- kolla_action != "config"
- inventory_hostname in groups[service.group]
- service.enabled | bool
- config_json.changed | bool
or qinling_conf.changed | bool
or policy_overwriting.changed | bool
or qinling_engine_container.changed | bool

@ -0,0 +1,3 @@
---
dependencies:
- { role: common }

@ -0,0 +1,38 @@
---
- name: Creating Qinling database
become: true
kolla_toolbox:
module_name: mysql_db
module_args:
login_host: "{{ database_address }}"
login_port: "{{ database_port }}"
login_user: "{{ database_user }}"
login_password: "{{ database_password }}"
name: "{{ qinling_database_name }}"
register: database
run_once: True
delegate_to: "{{ groups['qinling-api'][0] }}"
when:
- not use_preconfigured_databases | bool
- name: Creating Qinling database user and setting permissions
become: true
kolla_toolbox:
module_name: mysql_user
module_args:
login_host: "{{ database_address }}"
login_port: "{{ database_port }}"
login_user: "{{ database_user }}"
login_password: "{{ database_password }}"
name: "{{ qinling_database_user }}"
password: "{{ qinling_database_password }}"
host: "%"
priv: "{{ qinling_database_name }}.*:ALL"
append_privs: "yes"
run_once: True
delegate_to: "{{ groups['qinling-api'][0] }}"
when:
- not use_preconfigured_databases | bool
- include_tasks: bootstrap_service.yml
when: database.changed or use_preconfigured_databases | bool

@ -0,0 +1,20 @@
---
- name: Running Qinling bootstrap container
vars:
qinling_api: "{{ qinling_services['qinling-api'] }}"
become: true
kolla_docker:
action: "start_container"
common_options: "{{ docker_common_options }}"
detach: False
environment:
KOLLA_BOOTSTRAP:
KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
image: "{{ qinling_api.image }}"
labels:
BOOTSTRAP:
name: "bootstrap_qinling"
restart_policy: "never"
volumes: "{{ qinling_api.volumes|reject('equalto', '')|list }}"
run_once: True
delegate_to: "{{ groups[qinling_api.group][0] }}"

@ -0,0 +1 @@
---

@ -0,0 +1,7 @@
---
- name: Cloning qinling source repository for development
git:
repo: "{{ qinling_git_repository }}"
dest: "{{ kolla_dev_repos_directory }}/{{ project_name }}"
update: "{{ qinling_dev_repos_pull }}"
version: "{{ qinling_source_version }}"

@ -0,0 +1,104 @@
---
- name: Ensuring config directories exist
file:
path: "{{ node_config_directory }}/{{ item.key }}"
state: "directory"
owner: "{{ config_owner_user }}"
group: "{{ config_owner_group }}"
mode: "0770"
become: true
when:
- inventory_hostname in groups[item.value.group]
- item.value.enabled | bool
with_dict: "{{ qinling_services }}"
- include_tasks: external_kubernetes.yml
when:
- (enable_qinling | bool) and (qinling_kubernetes_certificates | bool)
- inventory_hostname in groups['qinling-engine']
- name: Check if policies shall be overwritten
local_action: stat path="{{ item }}"
run_once: True
register: qinling_policy
with_first_found:
- files: "{{ supported_policy_format_list }}"
paths:
- "{{ node_custom_config }}/qinling/"
skip: true
- name: Set qinling policy file
set_fact:
qinling_policy_file: "{{ qinling_policy.results.0.stat.path | basename }}"
qinling_policy_file_path: "{{ qinling_policy.results.0.stat.path }}"
when:
- qinling_policy.results
- name: Copying over config.json files for services
template:
src: "{{ item.key }}.json.j2"
dest: "{{ node_config_directory }}/{{ item.key }}/config.json"
mode: "0660"
become: true
register: qinling_config_jsons
when:
- inventory_hostname in groups[item.value.group]
- item.value.enabled | bool
with_dict: "{{ qinling_services }}"
notify:
- Restart {{ item.key }} container
- name: Copying over qinling.conf
vars:
service_name: "{{ item.key }}"
merge_configs:
sources:
- "{{ role_path }}/templates/qinling.conf.j2"
- "{{ node_custom_config }}/global.conf"
- "{{ node_custom_config }}/qinling.conf"
- "{{ node_custom_config }}/qinling/{{ item.key }}.conf"
- "{{ node_custom_config }}/qinling/{{ inventory_hostname }}/qinling.conf"
dest: "{{ node_config_directory }}/{{ item.key }}/qinling.conf"
mode: "0660"
become: true
register: qinling_confs
when:
- inventory_hostname in groups[item.value.group]
- item.value.enabled | bool
with_dict: "{{ qinling_services }}"
notify:
- Restart {{ item.key }} container
- name: Copying over existing policy file
template:
src: "{{ qinling_policy_file_path }}"
dest: "{{ node_config_directory }}/{{ item.key }}/{{ qinling_policy_file }}"
mode: "0660"
become: true
register: qinling_policy_overwriting
when:
- qinling_policy_file is defined
- inventory_hostname in groups[item.value.group]
- item.value.enabled | bool
with_dict: "{{ qinling_services }}"
notify:
- Restart {{ item.key }} container
- name: Check qinling containers
become: true
kolla_docker:
action: "compare_container"
common_options: "{{ docker_common_options }}"
name: "{{ item.value.container_name }}"
image: "{{ item.value.image }}"
volumes: "{{ item.value.volumes|reject('equalto', '')|list }}"
dimensions: "{{ item.value.dimensions }}"
environment: "{{ item.value.environment }}"
register: check_qinling_containers
when:
- kolla_action != "config"
- inventory_hostname in groups[item.value.group]
- item.value.enabled | bool
with_dict: "{{ qinling_services }}"
notify:
- Restart {{ item.key }} container

@ -0,0 +1,16 @@
---
- include_tasks: register.yml
when: inventory_hostname in groups['qinling-api']
- include_tasks: config.yml
when: inventory_hostname in groups['qinling-api'] or
inventory_hostname in groups['qinling-engine']
- include_tasks: clone.yml
when: qinling_dev_mode | bool
- include_tasks: bootstrap.yml
when: inventory_hostname in groups['qinling-api']
- name: Flush handlers
meta: flush_handlers

@ -0,0 +1,19 @@
---
- name: Copy over Kubernetes certificates files for qinling-engine
copy:
src: "{{ item }}"
dest: "{{ node_config_directory }}/qinling-engine/"
mode: "0660"
owner: "{{ config_owner_user }}"
group: "{{ config_owner_group }}"
become: true
register: qinling_engine_kubernetes_files
with_items:
- "{{ node_custom_config }}/qinling/qinling-engine/kubernetes_ca.crt"
- "{{ node_custom_config }}/qinling/qinling-engine/kubernetes.crt"
- "{{ node_custom_config }}/qinling/qinling-engine/kubernetes.key"
when:
- qinling_kubernetes_certificates | bool
- inventory_hostname in groups['qinling-engine']
notify:
- Restart qinling-engine container

@ -0,0 +1,7 @@
---
- name: "Configure haproxy for {{ project_name }}"
import_role:
role: haproxy-config
vars:
project_services: "{{ qinling_services }}"
tags: always

@ -0,0 +1,2 @@
---
- include_tasks: "{{ kolla_action }}.yml"

@ -0,0 +1,17 @@
---
- name: Get container facts
kolla_container_facts:
name:
- qinling_api
register: container_facts
- name: Checking free port for Qinling API
wait_for:
host: "{{ api_interface_address }}"
port: "{{ qinling_api_port }}"
connect_timeout: 1
timeout: 1
state: stopped
when:
- container_facts['qinling_api'] is not defined
- inventory_hostname in groups['qinling-api']

@ -0,0 +1,11 @@
---
- name: Pulling qinling images
become: true
kolla_docker:
action: "pull_image"
common_options: "{{ docker_common_options }}"
image: "{{ item.value.image }}"
when:
- inventory_hostname in groups[item.value.group]
- item.value.enabled | bool
with_dict: "{{ qinling_services }}"

@ -0,0 +1,2 @@
---
- include_tasks: deploy.yml

@ -0,0 +1,34 @@
---
- name: Creating the Qinling service and endpoint
become: true
kolla_toolbox:
module_name: "kolla_keystone_service"
module_args:
service_name: "qinling"
service_type: "function-engine"
description: "Function Service"
endpoint_region: "{{ openstack_region_name }}"
url: "{{ item.url }}"
interface: "{{ item.interface }}"
region_name: "{{ openstack_region_name }}"
auth: "{{ openstack_qinling_auth }}"
endpoint_type: "{{ openstack_interface }}"
run_once: True
with_items:
- {'interface': 'admin', 'url': '{{ qinling_admin_endpoint }}'}
- {'interface': 'internal', 'url': '{{ qinling_internal_endpoint }}'}
- {'interface': 'public', 'url': '{{ qinling_public_endpoint }}'}
- name: Creating the Qinling project, user, and role
become: true
kolla_toolbox:
module_name: "kolla_keystone_user"
module_args:
project: "service"
user: "{{ qinling_keystone_user }}"
password: "{{ qinling_keystone_password }}"
role: "admin"
region_name: "{{ openstack_region_name }}"
auth: "{{ openstack_qinling_auth }}"
endpoint_type: "{{ openstack_interface }}"
run_once: True

@ -0,0 +1,6 @@
---
- import_role:
role: service-stop
vars:
project_services: "{{ qinling_services }}"
service_name: "{{ project_name }}"

@ -0,0 +1,7 @@
---
- include_tasks: config.yml
- include_tasks: bootstrap_service.yml
- name: Flush handlers
meta: flush_handlers

@ -0,0 +1,24 @@
{
"command": "qinling-api --config-file /etc/qinling/qinling.conf",
"config_files": [
{
"source": "{{ container_config_directory }}/qinling.conf",
"dest": "/etc/qinling/qinling.conf",
"owner": "qinling",
"perm": "0600"
}{% if qinling_policy_file is defined %},
{
"source": "{{ container_config_directory }}/{{ qinling_policy_file }}",
"dest": "/etc/qinling/{{ qinling_policy_file }}",
"owner": "qinling",
"perm": "0600"
}{% endif %}
],
"permissions": [
{
"path": "/var/log/kolla/qinling",
"owner": "qinling:qinling",
"recurse": true
}
]
}

@ -0,0 +1,47 @@
{
"command": "qinling-engine --config-file /etc/qinling/qinling.conf",
"config_files": [
{
"source": "{{ container_config_directory }}/qinling.conf",
"dest": "/etc/qinling/qinling.conf",
"owner": "qinling",
"perm": "0600"
}{% if qinling_policy_file is defined %},
{
"source": "{{ container_config_directory }}/{{ qinling_policy_file }}",
"dest": "/etc/qinling/{{ qinling_policy_file }}",
"owner": "qinling",
"perm": "0600"
}{% endif %}{% if qinling_kubernetes_certificates is defined and qinling_kubernetes_certificates | bool %},
{
"source": "{{ container_config_directory }}/kubernetes_ca.crt",
"dest": "/etc/qinling/pki/kubernetes/ca.crt",
"owner": "qinling",
"perm": "0600"
},
{
"source": "{{ container_config_directory }}/kubernetes.crt",
"dest": "/etc/qinling/pki/kubernetes/qinling.crt",
"owner": "qinling",
"perm": "0600"
},
{
"source": "{{ container_config_directory }}/kubernetes.key",
"dest": "/etc/qinling/pki/kubernetes/qinling.key",
"owner": "qinling",
"perm": "0600"
}{% endif %}
],
"permissions": [
{
"path": "/var/lib/qinling",
"owner": "qinling:qinling",
"recurse": true
},
{
"path": "/var/log/kolla/qinling",
"owner": "qinling:qinling",
"recurse": true
}
]
}

@ -0,0 +1,62 @@
[DEFAULT]
debug = {{ qinling_logging_debug }}
log_dir = /var/log/kolla/qinling
transport_url = {{ rpc_transport_url }}
{% if service_name == 'qinling-api' %}
[api]
port = {{ qinling_api_port }}
host = {{ api_interface_address }}
api_workers = {{ openstack_service_workers }}
{% endif %}
{% if service_name == 'qinling-engine' %}
[engine]
host = {{ api_interface_address }}
{% endif %}
[database]
connection = mysql+pymysql://{{ qinling_database_user }}:{{ qinling_database_password }}@{{ qinling_database_address }}/{{ qinling_database_name }}
max_retries = -1
[keystone_authtoken]
www_authenticate_uri = {{ keystone_internal_url }}/v3
auth_url = {{ keystone_admin_url }}
auth_type = password
project_domain_name = {{ default_project_domain_name }}
user_domain_name = {{ default_user_domain_name }}
project_name = service
username = {{ qinling_keystone_user }}
password = {{ qinling_keystone_password }}
region_name = {{ openstack_region_name }}
memcache_security_strategy = ENCRYPT
memcache_secret_key = {{ memcache_secret_key }}
memcached_servers = {% for host in groups['memcached'] %}{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ memcached_port }}{% if not loop.last %},{% endif %}{% endfor %}
[storage]
file_system_dir = /var/lib/qinling/package
[etcd]
{% if enable_etcd | bool %}
host = {{ api_interface_address }}
port = {{ etcd_client_port }}
protocol = {{ internal_protocol }}
{% endif %}
[oslo_messaging_notifications]
transport_url = {{ notify_transport_url }}
{% if enable_ceilometer | bool %}
driver = messagingv2
topics = notifications
{% else %}
driver = noop
{% endif %}
{% if qinling_policy_file is defined %}
[oslo_policy]
policy_file = {{ qinling_policy_file }}
{% endif %}
[oslo_middleware]
enable_proxy_headers_parsing = True

@ -69,6 +69,7 @@
- enable_placement_{{ enable_placement | bool }}
- enable_prometheus_{{ enable_prometheus | bool }}
- enable_qdrouterd_{{ enable_qdrouterd | bool }}
- enable_qinling_{{ enable_qinling | bool }}
- enable_rabbitmq_{{ enable_rabbitmq | bool }}
- enable_rally_{{ enable_rally | bool }}
- enable_redis_{{ enable_redis | bool }}
@ -302,6 +303,11 @@
tasks_from: loadbalancer
tags: prometheus
when: enable_prometheus | bool
- include_role:
role: qinling
tasks_from: loadbalancer
tags: qinling
when: enable_qinling | bool
- include_role:
role: rabbitmq
tasks_from: loadbalancer
@ -863,6 +869,18 @@
tags: mistral,
when: enable_mistral | bool }
- name: Apply role qinling
gather_facts: false
hosts:
- qinling-api
- qinling-engine
- '&enable_qinling_True'
serial: '{{ kolla_serial|default("0") }}'
roles:
- { role: qinling,
tags: qinling,
when: enable_qinling | bool }
- name: Apply role sahara
gather_facts: false
hosts:

@ -10,6 +10,7 @@ compute services like HyperV, XenServer and so on.
hyperv-guide
nova-fake-driver
qinling-guide
vmware-guide
xenserver-guide
zun-guide

@ -0,0 +1,96 @@
.. _qinling-guide:
=========================
Qinling - Function Engine
=========================
Overview
~~~~~~~~
Qinling aims to provide a platform to support serverless functions
(like AWS Lambda). Qinling supports different container orchestration
platforms (Kubernetes/Swarm, etc...) and different function package storage
backends (local/Swift/S3) by nature using plugin mechanism.
Kolla deploys Qinling API and Qinling Engine containers which are the main
Qinling components but it needs to be connected to an existing container
orchestration platforms.
Apply custom policies to Qinling API
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Custom policies could be apply by creating ``policy.json`` file under
``/etc/kolla/config/qinling`` directory.
Connect to an existing Kubernetes cluster
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Certificates
------------
``qinling-engine`` authenticates to Kubernetes by using certificates.
.. note::
If the cluster has not been created with OpenStack Magnum then
certificates need to be gathered using different methods that will not
be mentioned here.
If the Kubernetes cluster has been deployed with OpenStack Magnum then the
OpenStack client should be used to retrieve the certificates.
.. code-block:: console
openstack coe cluster config --dir . 687f7476-5604-4b44-8b09-b7a4f3fdbd64 --output-certs
Where ``687f7476-5604-4b44-8b09-b7a4f3fdbd64`` is the Kubernetes cluster ID
created with Magnum.
Four files should have been generated:
- ``ca.pem``
- ``cert.pem``
- ``key.pem``
- ``config``
Only ``ca.pem``, ``cert.pem`` and ``key.pem`` will be used, these files have
to be stored in ``/etc/kolla/config/qinling/qinling-engine`` directory under
these file name:
- ``ca.pem``: ``/etc/kolla/config/qinling/qinling-engine/kubernetes_ca.crt``
- ``cert.pem``: ``/etc/kolla/config/qinling/qinling-engine/kubernetes.crt``
- ``key.pem``: ``/etc/kolla/config/qinling/qinling-engine/kubernetes.key``
Declare ``qinling_kubernetes_certificates`` variable in
``/etc/kolla/globals.yml``:
.. code-block:: yaml
qinling_kubernetes_certificates: "yes"
Kubernetes cluster
------------------
``qinling-engine`` needs to know where to connect, the information is
provided by options under ``[kubernetes]`` section inside ``qinling.conf``
configuration file.
As mentioned above, these settings are only required by ``qinling-engine``,
put the content in ``/etc/kolla/config/qinling/qinling-engine.conf``.
.. code-block:: ini
[kubernetes]
kube_host = https://192.168.1.168:6443
use_api_certificate = True
ssl_ca_cert = /etc/qinling/pki/kubernetes/ca.crt
cert_file = /etc/qinling/pki/kubernetes/qinling.crt
key_file = /etc/qinling/pki/kubernetes/qinling.key
trusted_cidrs = 192.168.1.0/24,10.0.0.53/32
``kube_host`` is the the Kubernetes cluster API address, ``https`` protocol
have to be defined.
``trusted_cidrs`` is a list of CIDR trusted by the Kubernetes cluster defined
by a network policy under the ``qinling`` namespace.

@ -236,6 +236,7 @@ kolla_internal_vip_address: "10.10.10.254"
#enable_horizon_neutron_lbaas: "{{ enable_neutron_lbaas | bool }}"
#enable_horizon_neutron_vpnaas: "{{ enable_neutron_vpnaas | bool }}"
#enable_horizon_octavia: "{{ enable_octavia | bool }}"
#enable_horizon_qinling: "{{ enable_qinling | bool }}"
#enable_horizon_sahara: "{{ enable_sahara | bool }}"
#enable_horizon_searchlight: "{{ enable_searchlight | bool }}"
#enable_horizon_senlin: "{{ enable_senlin | bool }}"
@ -288,6 +289,7 @@ kolla_internal_vip_address: "10.10.10.254"
#enable_placement: "{{ enable_nova }}"
#enable_prometheus: "no"
#enable_qdrouterd: "no"
#enable_qinling: "no"
#enable_rally: "no"
#enable_redis: "no"
#enable_sahara: "no"

@ -196,6 +196,9 @@ vitrage_keystone_password:
memcache_secret_key:
qinling_database_password:
qinling_keystone_password:
# HMAC secret key
osprofiler_secret:

@ -0,0 +1,5 @@
---
features:
- Adds Qinling Ansible role. Qinling is an OpenStack project
to provide "Function as a Service". This project aims to
provide a platform to support serverless functions.

@ -159,6 +159,9 @@ monitoring
[magnum:children]
control
[qinling:children]
control
[sahara:children]
control
@ -457,6 +460,13 @@ magnum
[magnum-conductor:children]
magnum
# Qinling
[qinling-api:children]
qinling
[qinling-engine:children]
qinling
# Solum
[solum-api:children]
solum