diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml index 51dc3a652e..2b52c1dfa0 100644 --- a/ansible/group_vars/all.yml +++ b/ansible/group_vars/all.yml @@ -602,6 +602,7 @@ enable_openvswitch: "{{ enable_neutron | bool and neutron_plugin_agent != 'linux enable_ovs_dpdk: "no" enable_osprofiler: "no" enable_panko: "no" +enable_placement: "{{ enable_nova }}" enable_qdrouterd: "{{ 'yes' if om_rpc_transport == 'amqp' else 'no' }}" enable_rally: "no" enable_redis: "no" diff --git a/ansible/roles/nova/defaults/main.yml b/ansible/roles/nova/defaults/main.yml index cc35dd4eb4..8b0152ef3d 100644 --- a/ansible/roles/nova/defaults/main.yml +++ b/ansible/roles/nova/defaults/main.yml @@ -36,30 +36,6 @@ nova_services: - "{% if enable_shared_var_lib_nova_mnt | bool %}/var/lib/nova/mnt:/var/lib/nova/mnt:shared{% endif %}" - "{{ kolla_dev_repos_directory ~ '/nova/nova:/var/lib/kolla/venv/lib/python2.7/site-packages/nova' if nova_dev_mode | bool else '' }}" dimensions: "{{ nova_ssh_dimensions }}" - placement-api: - container_name: "placement_api" - group: "placement-api" - image: "{{ placement_api_image_full }}" - enabled: True - volumes: - - "{{ node_config_directory }}/placement-api/:{{ container_config_directory }}/:ro" - - "/etc/localtime:/etc/localtime:ro" - - "kolla_logs:/var/log/kolla/" - - "{{ kolla_dev_repos_directory ~ '/nova/nova:/var/lib/kolla/venv/lib/python2.7/site-packages/nova' if nova_dev_mode | bool else '' }}" - dimensions: "{{ placement_api_dimensions }}" - haproxy: - placement_api: - enabled: "{{ enable_nova }}" - mode: "http" - external: false - port: "{{ placement_api_port }}" - listen_port: "{{ placement_api_listen_port }}" - placement_api_external: - enabled: "{{ enable_nova }}" - mode: "http" - external: true - port: "{{ placement_api_port }}" - listen_port: "{{ placement_api_listen_port }}" nova-api: container_name: "nova_api" group: "nova-api" @@ -341,13 +317,8 @@ nova_serialproxy_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{ nova_serialproxy_tag: "{{ nova_tag }}" nova_serialproxy_image_full: "{{ nova_serialproxy_image }}:{{ nova_serialproxy_tag }}" -placement_api_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ nova_install_type }}-nova-placement-api" -placement_api_tag: "{{ nova_tag }}" -placement_api_image_full: "{{ placement_api_image }}:{{ placement_api_tag }}" - nova_libvirt_dimensions: "{{ default_container_dimensions }}" nova_ssh_dimensions: "{{ default_container_dimensions }}" -placement_api_dimensions: "{{ default_container_dimensions }}" nova_api_dimensions: "{{ default_container_dimensions }}" nova_consoleauth_dimensions: "{{ default_container_dimensions }}" nova_novncproxy_dimensions: "{{ default_container_dimensions }}" @@ -375,14 +346,9 @@ nova_admin_endpoint: "{{ admin_protocol }}://{{ nova_internal_fqdn }}:{{ nova_ap nova_internal_endpoint: "{{ internal_protocol }}://{{ nova_internal_fqdn }}:{{ nova_api_port }}/v2.1/%(tenant_id)s" nova_public_endpoint: "{{ public_protocol }}://{{ nova_external_fqdn }}:{{ nova_api_port }}/v2.1/%(tenant_id)s" -placement_admin_endpoint: "{{ admin_protocol }}://{{ placement_internal_fqdn }}:{{ placement_api_port }}" -placement_internal_endpoint: "{{ internal_protocol }}://{{ placement_internal_fqdn }}:{{ placement_api_port }}" -placement_public_endpoint: "{{ public_protocol }}://{{ placement_external_fqdn }}:{{ placement_api_port }}" - nova_logging_debug: "{{ openstack_logging_debug }}" openstack_nova_auth: "{{ openstack_auth }}" -openstack_placement_auth: "{{ openstack_auth }}" nova_compute_host_rp_filter_mode: 0 nova_enable_rolling_upgrade: "yes" diff --git a/ansible/roles/nova/handlers/main.yml b/ansible/roles/nova/handlers/main.yml index a634128179..b46d00fc55 100644 --- a/ansible/roles/nova/handlers/main.yml +++ b/ansible/roles/nova/handlers/main.yml @@ -1,30 +1,4 @@ --- -- name: Restart placement-api container - vars: - service_name: "placement-api" - service: "{{ nova_services[service_name] }}" - config_json: "{{ config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" - nova_conf: "{{ nova_confs.results|selectattr('item.key', 'equalto', service_name)|first }}" - policy_overwriting: "{{ nova_policy_overwriting.results|selectattr('item.key', 'equalto', service_name)|first }}" - placement_api_container: "{{ check_nova_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 }}" - dimensions: "{{ service.dimensions }}" - when: - - kolla_action != "config" - - inventory_hostname in groups[service.group] - - service.enabled | bool - - config_json.changed | bool - or nova_conf.changed | bool - or policy_overwriting.changed | bool - or placement_api_wsgi_conf | changed - or placement_api_container.changed | bool - - name: Restart nova-conductor container vars: service_name: "nova-conductor" diff --git a/ansible/roles/nova/tasks/config.yml b/ansible/roles/nova/tasks/config.yml index 22c537b1cd..60cab45be8 100644 --- a/ansible/roles/nova/tasks/config.yml +++ b/ansible/roles/nova/tasks/config.yml @@ -82,7 +82,6 @@ become: true vars: services_require_nova_conf: - - placement-api - nova-api - nova-compute - nova-compute-ironic @@ -129,20 +128,6 @@ notify: - Restart nova-libvirt container -- name: Copying over placement-api wsgi configuration - become: true - vars: - service: "{{ nova_services['placement-api'] }}" - template: - src: "placement-api-wsgi.conf.j2" - dest: "{{ node_config_directory }}/placement-api/placement-api-wsgi.conf" - register: placement_api_wsgi_conf - when: - - inventory_hostname in groups[service.group] - - service.enabled | bool - notify: - - Restart placement-api container - - name: Copying files for nova-ssh become: true vars: @@ -201,7 +186,6 @@ become: true vars: services_require_policy_json: - - placement-api - nova-api - nova-compute - nova-compute-ironic diff --git a/ansible/roles/nova/tasks/precheck.yml b/ansible/roles/nova/tasks/precheck.yml index d20fbb74b2..8a639cb012 100644 --- a/ansible/roles/nova/tasks/precheck.yml +++ b/ansible/roles/nova/tasks/precheck.yml @@ -8,7 +8,6 @@ - nova_spicehtml5proxy - nova_ssh - nova_libvirt - - placement_api register: container_facts - name: Checking available compute nodes in inventory @@ -119,20 +118,6 @@ - nova_libvirt.enabled | bool - inventory_hostname in groups[nova_libvirt.group] -- name: Checking free port for Nova Placement API - vars: - placement_api: "{{ nova_services['placement-api'] }}" - wait_for: - host: "{{ api_interface_address }}" - port: "{{ placement_api_listen_port }}" - connect_timeout: 1 - timeout: 1 - state: stopped - when: - - container_facts['placement_api'] is not defined - - inventory_hostname in groups[placement_api.group] - - placement_api.enabled | bool - - name: Checking that libvirt is not running vars: nova_libvirt: "{{ nova_services['nova-libvirt'] }}" diff --git a/ansible/roles/nova/tasks/register.yml b/ansible/roles/nova/tasks/register.yml index 60a6c1c7ae..e0d0acb9c6 100644 --- a/ansible/roles/nova/tasks/register.yml +++ b/ansible/roles/nova/tasks/register.yml @@ -20,10 +20,6 @@ - {'name': 'nova', 'service_type': 'compute', 'interface': 'admin', 'url': '{{ nova_admin_endpoint }}', 'description': 'OpenStack Compute Service'} - {'name': 'nova', 'service_type': 'compute', 'interface': 'internal', 'url': '{{ nova_internal_endpoint }}', 'description': 'OpenStack Compute Service'} - {'name': 'nova', 'service_type': 'compute', 'interface': 'public', 'url': '{{ nova_public_endpoint }}', 'description': 'OpenStack Compute Service'} - - {'name': 'placement', 'service_type': 'placement', 'interface': 'admin', 'url': '{{ placement_admin_endpoint }}', 'description': 'Placement Service'} - - {'name': 'placement', 'service_type': 'placement', 'interface': 'internal', 'url': '{{ placement_internal_endpoint }}', 'description': 'Placement Service'} - - {'name': 'placement', 'service_type': 'placement', 'interface': 'public', 'url': '{{ placement_public_endpoint }}', 'description': 'Placement Service'} - - name: Creating the Nova project, user, and role kolla_toolbox: @@ -37,16 +33,3 @@ auth: "{{ openstack_nova_auth }}" endpoint_type: "{{ openstack_interface }}" run_once: True - -- name: Creating the placement project, user, and role - kolla_toolbox: - module_name: "kolla_keystone_user" - module_args: - project: "service" - user: "{{ placement_keystone_user }}" - password: "{{ placement_keystone_password }}" - role: "admin" - region_name: "{{ openstack_region_name }}" - auth: "{{ openstack_placement_auth }}" - endpoint_type: "{{ openstack_interface }}" - run_once: True diff --git a/ansible/roles/nova/templates/placement-api.json.j2 b/ansible/roles/nova/templates/placement-api.json.j2 deleted file mode 100644 index 395f7d06fa..0000000000 --- a/ansible/roles/nova/templates/placement-api.json.j2 +++ /dev/null @@ -1,32 +0,0 @@ -{% set apache_binary = 'apache2' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd' %} -{% set apache_conf_dir = 'apache2/conf-enabled' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd/conf.d' %} -{ - "command": "/usr/sbin/{{ apache_binary }} -DFOREGROUND", - "config_files": [ - { - "source": "{{ container_config_directory }}/nova.conf", - "dest": "/etc/nova/nova.conf", - "owner": "nova", - "perm": "0600" - }{% if nova_policy_file is defined %}, - { - "source": "{{ container_config_directory }}/{{ nova_policy_file }}", - "dest": "/etc/nova/{{ nova_policy_file }}", - "owner": "nova", - "perm": "0600" - }{% endif %}, - { - "source": "{{ container_config_directory }}/placement-api-wsgi.conf", - "dest": "/etc/{{ apache_conf_dir }}/placement-api-wsgi.conf", - "owner": "nova", - "perm": "0600" - } - ], - "permissions": [ - { - "path": "/var/log/kolla/nova", - "owner": "nova:nova", - "recurse": true - } - ] -} diff --git a/ansible/roles/placement/defaults/main.yml b/ansible/roles/placement/defaults/main.yml new file mode 100644 index 0000000000..a25496f28d --- /dev/null +++ b/ansible/roles/placement/defaults/main.yml @@ -0,0 +1,87 @@ +--- +project_name: "placement" + +placement_services: + placement-api: + container_name: "placement_api" + group: "placement-api" + image: "{{ placement_api_image_full }}" + enabled: True + volumes: + - "{{ node_config_directory }}/placement-api/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "kolla_logs:/var/log/kolla/" + - "{{ kolla_dev_repos_directory ~ '/placement/placement:/var/lib/kolla/venv/lib/python2.7/site-packages/placement' if placement_dev_mode | bool else '' }}" + dimensions: "{{ placement_api_dimensions }}" + haproxy: + placement_api: + enabled: "{{ enable_placement }}" + mode: "http" + external: false + port: "{{ placement_api_port }}" + listen_port: "{{ placement_api_listen_port }}" + placement_api_external: + enabled: "{{ enable_placement }}" + mode: "http" + external: true + port: "{{ placement_api_port }}" + listen_port: "{{ placement_api_listen_port }}" + +#################### +# Database +#################### +placement_database_name: "placement" +placement_database_user: "{% if use_preconfigured_databases | bool and use_common_mariadb_user | bool %}{{ database_user }}{% else %}placement{% endif %}" +placement_database_address: "{{ database_address }}:{{ database_port }}" + +#################### +# Docker +#################### +placement_install_type: "{{ kolla_install_type }}" +placement_tag: "{{ openstack_release }}" + +placement_api_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ placement_install_type }}-placement-api" +placement_api_tag: "{{ placement_tag }}" +placement_api_image_full: "{{ placement_api_image }}:{{ placement_api_tag }}" + +placement_api_dimensions: "{{ default_container_dimensions }}" + +#################### +# OpenStack +#################### +placement_admin_endpoint: "{{ admin_protocol }}://{{ placement_internal_fqdn }}:{{ placement_api_port }}" +placement_internal_endpoint: "{{ internal_protocol }}://{{ placement_internal_fqdn }}:{{ placement_api_port }}" +placement_public_endpoint: "{{ public_protocol }}://{{ placement_external_fqdn }}:{{ placement_api_port }}" + +placement_logging_debug: "{{ openstack_logging_debug }}" + +openstack_placement_auth: "{{ openstack_auth }}" + + +#################### +# Notification +#################### +placement_notification_topics: + - name: notifications + enabled: "{{ enable_ceilometer | bool or enable_searchlight | bool or enable_neutron_infoblox_ipam_agent | bool }}" + - name: notifications_designate + enabled: "{{ enable_designate | bool }}" + +placement_enabled_notification_topics: "{{ placement_notification_topics | selectattr('enabled', 'equalto', true) | list }}" + + +#################### +# Kolla +#################### +placement_git_repository: "{{ kolla_dev_repos_git }}/{{ project_name }}" +placement_dev_repos_pull: "{{ kolla_dev_repos_pull }}" +placement_dev_mode: "{{ kolla_dev_mode }}" +placement_source_version: "{{ kolla_source_version }}" + +#################### +# Upgrade +#################### +nova_api_database_name: "nova_api" +nova_api_database_user: "{% if use_preconfigured_databases | bool and use_common_mariadb_user | bool %}{{ database_user }}{% else %}nova_api{% endif %}" +nova_api_database_host: "{{ database_address }}" +placement_database_host: "{{ database_address }}" diff --git a/ansible/roles/placement/handlers/main.yml b/ansible/roles/placement/handlers/main.yml new file mode 100644 index 0000000000..ffeb23b499 --- /dev/null +++ b/ansible/roles/placement/handlers/main.yml @@ -0,0 +1,15 @@ +--- +- name: Restart placement-api container + become: true + vars: + service_name: "placement-api" + service: "{{ placement_services[service_name] }}" + 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 }}" + dimensions: "{{ service.dimensions }}" + when: + - kolla_action != "config" diff --git a/ansible/roles/placement/meta/main.yml b/ansible/roles/placement/meta/main.yml new file mode 100644 index 0000000000..6b4fff8fef --- /dev/null +++ b/ansible/roles/placement/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - { role: common } diff --git a/ansible/roles/placement/tasks/bootstrap.yml b/ansible/roles/placement/tasks/bootstrap.yml new file mode 100644 index 0000000000..0628807782 --- /dev/null +++ b/ansible/roles/placement/tasks/bootstrap.yml @@ -0,0 +1,65 @@ +--- +- name: Creating placement databases + 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: "{{ placement_database_name }}" + register: database + run_once: True + delegate_to: "{{ groups['placement-api'][0] }}" + when: + - not use_preconfigured_databases | bool + +- name: Creating placement databases user and setting permissions + 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: "{{ placement_database_user }}" + password: "{{ placement_database_password }}" + host: "%" + priv: "{{ placement_database_name }}.*:ALL" + append_privs: "yes" + run_once: True + delegate_to: "{{ groups['placement-api'][0] }}" + when: + - database.changed + - not use_preconfigured_databases | bool + +# TODO(egonzalez): Remove this task once stein is release as will not be required to migrate data. +# Error codes https://github.com/openstack/placement/blob/master/tools/mysql-migrate-db.sh#L230 +- name: Migrate placement database + vars: + placement_api: "{{ placement_services['placement-api'] }}" + become: true + kolla_docker: + action: "start_container" + command: bash -c 'sudo -E kolla_set_configs && bash /opt/mysql-migrate-db.sh --migrate /etc/placement/migrate-db.rc' + common_options: "{{ docker_common_options }}" + detach: False + image: "{{ placement_api.image }}" + labels: + BOOTSTRAP: + name: "migrate_placement_database" + restart_policy: "never" + volumes: "{{ placement_api.volumes|reject('equalto', '')|list }}" + register: migrate_placement + changed_when: + - migrate_placement is success + - migrate_placement.rc == 0 + failed_when: + - migrate_placement.rc not in [0, 3, 4] + run_once: True + delegate_to: "{{ groups[placement_api.group][0] }}" + when: + - kolla_action == "upgrade" + +- include_tasks: bootstrap_service.yml + when: database.changed or use_preconfigured_databases | bool diff --git a/ansible/roles/placement/tasks/bootstrap_service.yml b/ansible/roles/placement/tasks/bootstrap_service.yml new file mode 100644 index 0000000000..7d7b8e7b4f --- /dev/null +++ b/ansible/roles/placement/tasks/bootstrap_service.yml @@ -0,0 +1,20 @@ +--- +- name: Running placement bootstrap container + vars: + placement_api: "{{ placement_services['placement-api'] }}" + become: true + kolla_docker: + action: "start_container" + common_options: "{{ docker_common_options }}" + detach: False + environment: + KOLLA_BOOTSTRAP: + KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}" + image: "{{ placement_api.image }}" + labels: + BOOTSTRAP: + name: "bootstrap_placement" + restart_policy: "never" + volumes: "{{ placement_api.volumes|reject('equalto', '')|list }}" + run_once: True + delegate_to: "{{ groups[placement_api.group][0] }}" diff --git a/ansible/roles/placement/tasks/check.yml b/ansible/roles/placement/tasks/check.yml new file mode 100644 index 0000000000..ed97d539c0 --- /dev/null +++ b/ansible/roles/placement/tasks/check.yml @@ -0,0 +1 @@ +--- diff --git a/ansible/roles/placement/tasks/clone.yml b/ansible/roles/placement/tasks/clone.yml new file mode 100644 index 0000000000..cfe3fe3436 --- /dev/null +++ b/ansible/roles/placement/tasks/clone.yml @@ -0,0 +1,7 @@ +--- +- name: Cloning placement source repository for development + git: + repo: "{{ placement_git_repository }}" + dest: "{{ kolla_dev_repos_directory }}/{{ project_name }}" + update: "{{ placement_dev_repos_pull }}" + version: "{{ placement_source_version }}" diff --git a/ansible/roles/placement/tasks/config.yml b/ansible/roles/placement/tasks/config.yml new file mode 100644 index 0000000000..f8863f5af5 --- /dev/null +++ b/ansible/roles/placement/tasks/config.yml @@ -0,0 +1,124 @@ +--- +- name: Ensuring config directories exist + become: true + file: + path: "{{ node_config_directory }}/{{ item.key }}" + state: "directory" + owner: "{{ config_owner_user }}" + group: "{{ config_owner_group }}" + mode: "0770" + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ placement_services }}" + +- name: Check if policies shall be overwritten + local_action: stat path="{{ item }}" + run_once: True + register: placement_policy + with_first_found: + - files: "{{ supported_policy_format_list }}" + paths: + - "{{ node_custom_config }}/placement/" + skip: true + +- name: Set placement policy file + set_fact: + placement_policy_file: "{{ placement_policy.results.0.stat.path | basename }}" + placement_policy_file_path: "{{ placement_policy.results.0.stat.path }}" + when: + - placement_policy.results + +- name: Copying over config.json files for services + become: true + template: + src: "{{ item.key }}.json.j2" + dest: "{{ node_config_directory }}/{{ item.key }}/config.json" + mode: "0770" + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ placement_services }}" + notify: + - "Restart {{ item.key }} container" + +- name: Copying over placement.conf + become: true + vars: + service_name: "{{ item.key }}" + merge_configs: + sources: + - "{{ role_path }}/templates/placement.conf.j2" + - "{{ node_custom_config }}/global.conf" + - "{{ node_custom_config }}/placement.conf" + - "{{ node_custom_config }}/placement/{{ item.key }}.conf" + - "{{ node_custom_config }}/placement/{{ inventory_hostname }}/placement.conf" + dest: "{{ node_config_directory }}/{{ item.key }}/placement.conf" + mode: "0660" + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ placement_services }}" + notify: + - "Restart {{ item.key }} container" + +- name: Copying over placement-api wsgi configuration + become: true + vars: + service: "{{ placement_services['placement-api'] }}" + template: + src: "placement-api-wsgi.conf.j2" + dest: "{{ node_config_directory }}/placement-api/placement-api-wsgi.conf" + when: + - inventory_hostname in groups[service.group] + - service.enabled | bool + notify: + - Restart placement-api container + +- name: Copying over migrate-db.rc.j2 configuration + become: true + vars: + service: "{{ placement_services['placement-api'] }}" + template: + src: "migrate-db.rc.j2" + dest: "{{ node_config_directory }}/placement-api/migrate-db.rc" + when: + - inventory_hostname in groups[service.group] + - service.enabled | bool + notify: + - Restart placement-api container + +- name: Copying over existing policy file + become: true + template: + src: "{{ placement_policy_file_path }}" + dest: "{{ placement_config_directory }}/{{ item.key }}/{{ placement_policy_file }}" + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + - placement_policy_file is defined + with_dict: "{{ placement_services }}" + notify: + - "Restart {{ item.key }} container" + +# check whether the containers parameter is changed. If yes, trigger the handler +- name: Check placement containers + become: true + kolla_docker: + action: "compare_container" + common_options: "{{ docker_common_options }}" + name: "{{ item.value.container_name }}" + image: "{{ item.value.image }}" + environment: "{{ item.value.environment|default(omit) }}" + pid_mode: "{{ item.value.pid_mode|default('') }}" + ipc_mode: "{{ item.value.ipc_mode|default(omit) }}" + privileged: "{{ item.value.privileged|default(False) }}" + volumes: "{{ item.value.volumes|reject('equalto', '')|list }}" + dimensions: "{{ item.value.dimensions }}" + when: + - kolla_action != "config" + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ placement_services }}" + notify: + - "Restart {{ item.key }} container" diff --git a/ansible/roles/placement/tasks/deploy.yml b/ansible/roles/placement/tasks/deploy.yml new file mode 100644 index 0000000000..efb54983f5 --- /dev/null +++ b/ansible/roles/placement/tasks/deploy.yml @@ -0,0 +1,14 @@ +--- +- include_tasks: register.yml + when: inventory_hostname in groups['placement-api'] + +- include_tasks: clone.yml + when: placement_dev_mode | bool + +- include_tasks: config.yml + +- include_tasks: bootstrap.yml + when: inventory_hostname in groups['placement-api'] + +- name: Flush handlers + meta: flush_handlers diff --git a/ansible/roles/placement/tasks/loadbalancer.yml b/ansible/roles/placement/tasks/loadbalancer.yml new file mode 100644 index 0000000000..9b6b8970a5 --- /dev/null +++ b/ansible/roles/placement/tasks/loadbalancer.yml @@ -0,0 +1,7 @@ +--- +- name: "Configure haproxy for {{ project_name }}" + import_role: + role: haproxy-config + vars: + project_services: "{{ placement_services }}" + tags: always diff --git a/ansible/roles/placement/tasks/main.yml b/ansible/roles/placement/tasks/main.yml new file mode 100644 index 0000000000..bc5d1e6257 --- /dev/null +++ b/ansible/roles/placement/tasks/main.yml @@ -0,0 +1,2 @@ +--- +- include_tasks: "{{ kolla_action }}.yml" diff --git a/ansible/roles/placement/tasks/precheck.yml b/ansible/roles/placement/tasks/precheck.yml new file mode 100644 index 0000000000..dbb012036f --- /dev/null +++ b/ansible/roles/placement/tasks/precheck.yml @@ -0,0 +1,20 @@ +--- +- name: Get container facts + kolla_container_facts: + name: + - placement_api + register: container_facts + +- name: Checking free port for Placement API + vars: + placement_api: "{{ placement_services['placement-api'] }}" + wait_for: + host: "{{ api_interface_address }}" + port: "{{ placement_api_port }}" + connect_timeout: 1 + timeout: 1 + state: stopped + when: + - container_facts['placement_api'] is not defined + - inventory_hostname in groups[placement_api.group] + - placement_api.enabled | bool diff --git a/ansible/roles/placement/tasks/pull.yml b/ansible/roles/placement/tasks/pull.yml new file mode 100644 index 0000000000..f82b749393 --- /dev/null +++ b/ansible/roles/placement/tasks/pull.yml @@ -0,0 +1,11 @@ +--- +- name: Pulling placement 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: "{{ placement_services }}" diff --git a/ansible/roles/placement/tasks/reconfigure.yml b/ansible/roles/placement/tasks/reconfigure.yml new file mode 100644 index 0000000000..f670a5b78d --- /dev/null +++ b/ansible/roles/placement/tasks/reconfigure.yml @@ -0,0 +1,2 @@ +--- +- include_tasks: deploy.yml diff --git a/ansible/roles/placement/tasks/register.yml b/ansible/roles/placement/tasks/register.yml new file mode 100644 index 0000000000..e611cea6da --- /dev/null +++ b/ansible/roles/placement/tasks/register.yml @@ -0,0 +1,32 @@ +--- +- name: Creating the placement service and endpoint + kolla_toolbox: + module_name: "kolla_keystone_service" + module_args: + service_name: "{{ item.name }}" + service_type: "{{ item.service_type }}" + description: "{{ item.description }}" + endpoint_region: "{{ openstack_region_name }}" + url: "{{ item.url }}" + interface: "{{ item.interface }}" + region_name: "{{ openstack_region_name }}" + auth: "{{ openstack_placement_auth }}" + endpoint_type: "{{ openstack_interface }}" + run_once: True + with_items: + - {'name': 'placement', 'service_type': 'placement', 'interface': 'admin', 'url': '{{ placement_admin_endpoint }}', 'description': 'Placement Service'} + - {'name': 'placement', 'service_type': 'placement', 'interface': 'internal', 'url': '{{ placement_internal_endpoint }}', 'description': 'Placement Service'} + - {'name': 'placement', 'service_type': 'placement', 'interface': 'public', 'url': '{{ placement_public_endpoint }}', 'description': 'Placement Service'} + +- name: Creating the placement project, user, and role + kolla_toolbox: + module_name: "kolla_keystone_user" + module_args: + project: "service" + user: "{{ placement_keystone_user }}" + password: "{{ placement_keystone_password }}" + role: "admin" + region_name: "{{ openstack_region_name }}" + auth: "{{ openstack_placement_auth }}" + endpoint_type: "{{ openstack_interface }}" + run_once: True diff --git a/ansible/roles/placement/tasks/stop.yml b/ansible/roles/placement/tasks/stop.yml new file mode 100644 index 0000000000..eb98f416f9 --- /dev/null +++ b/ansible/roles/placement/tasks/stop.yml @@ -0,0 +1,6 @@ +--- +- import_role: + role: service-stop + vars: + project_services: "{{ placement_services }}" + service_name: "{{ project_name }}" diff --git a/ansible/roles/placement/tasks/upgrade.yml b/ansible/roles/placement/tasks/upgrade.yml new file mode 100644 index 0000000000..67e66dc7cd --- /dev/null +++ b/ansible/roles/placement/tasks/upgrade.yml @@ -0,0 +1,42 @@ +--- +- include_tasks: register.yml + when: inventory_hostname in groups['placement-api'] + +- include_tasks: clone.yml + when: placement_dev_mode | bool + +# TODO(mgoddard): Remove this in Train once all old containers have been +# stopped. +- name: "Stopping old placement-api containers" + kolla_docker: + action: "stop_container" + common_options: "{{ docker_common_options }}" + name: "placement_api" + +- include_tasks: config.yml + +- include_tasks: bootstrap.yml + when: inventory_hostname in groups['placement-api'] + +- name: Flush handlers + meta: flush_handlers + +- name: Perform Placement online data migration + vars: + placement_api: "{{ placement_services['placement-api'] }}" + become: true + kolla_docker: + action: "start_container" + common_options: "{{ docker_common_options }}" + detach: False + environment: + KOLLA_OSM: + KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}" + image: "{{ placement_api.image }}" + labels: + BOOTSTRAP: + name: "bootstrap_placement" + restart_policy: "never" + volumes: "{{ placement_api.volumes }}" + run_once: True + delegate_to: "{{ groups[placement_api.group][0] }}" diff --git a/ansible/roles/placement/templates/migrate-db.rc.j2 b/ansible/roles/placement/templates/migrate-db.rc.j2 new file mode 100644 index 0000000000..4d938836e6 --- /dev/null +++ b/ansible/roles/placement/templates/migrate-db.rc.j2 @@ -0,0 +1,8 @@ +NOVA_API_DB={{ nova_api_database_name }} +NOVA_API_USER={{ nova_api_database_user }} +NOVA_API_PASS={{ nova_api_database_password }} +NOVA_API_DB_HOST={{ nova_api_database_host }} +PLACEMENT_DB={{ placement_database_name }} +PLACEMENT_USER={{ placement_database_user }} +PLACEMENT_PASS={{ placement_database_password }} +PLACEMENT_DB_HOST={{ placement_database_host }} diff --git a/ansible/roles/nova/templates/placement-api-wsgi.conf.j2 b/ansible/roles/placement/templates/placement-api-wsgi.conf.j2 similarity index 61% rename from ansible/roles/nova/templates/placement-api-wsgi.conf.j2 rename to ansible/roles/placement/templates/placement-api-wsgi.conf.j2 index 556aa00a1f..60fd5a3706 100644 --- a/ansible/roles/nova/templates/placement-api-wsgi.conf.j2 +++ b/ansible/roles/placement/templates/placement-api-wsgi.conf.j2 @@ -1,10 +1,11 @@ -{% set log_dir = '/var/log/kolla/nova' %} -{% if nova_install_type == 'binary' %} +{% set log_dir = '/var/log/kolla/placement' %} +{% if placement_install_type == 'binary' %} {% set python_path = '/usr/lib/python3/dist-packages' if kolla_base_distro == 'ubuntu' else '/usr/lib/python2.7/site-packages' %} {% else %} {% set python_path = '/var/lib/kolla/venv/lib/python2.7/site-packages' %} {% endif %} -{% set wsgi_directory = '/usr/bin' if nova_install_type == 'binary' else '/var/lib/kolla/venv/bin' %} +{% set wsgi_directory = '/usr/bin' if placement_install_type == 'binary' else '/var/lib/kolla/venv/bin' %} + Listen {{ api_interface_address }}:{{ placement_api_listen_port }} ServerSignature Off @@ -12,12 +13,12 @@ ServerTokens Prod TraceEnable off - WSGIDaemonProcess placement-api processes={{ openstack_service_workers }} threads=1 user=nova group=nova display-name=%{GROUP} python-path={{ python_path }} + WSGIDaemonProcess placement-api processes={{ openstack_service_workers }} threads=1 user=placement group=placement display-name=%{GROUP} python-path={{ python_path }} WSGIProcessGroup placement-api -{% if kolla_install_type == 'binary' and kolla_base_distro == 'ubuntu' %} - WSGIScriptAlias / {{ wsgi_directory }}/python3-nova-placement-api +{% if placement_install_type == 'binary' and kolla_base_distro == 'ubuntu' %} + WSGIScriptAlias / {{ wsgi_directory }}/python3-placement-api {% else %} - WSGIScriptAlias / {{ wsgi_directory }}/nova-placement-api + WSGIScriptAlias / {{ wsgi_directory }}/placement-api {% endif %} WSGIApplicationGroup %{GLOBAL} WSGIPassAuthorization On @@ -28,10 +29,10 @@ TraceEnable off LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"" logformat CustomLog "{{ log_dir }}/placement-api-access.log" logformat -{% if kolla_install_type == 'binary' and kolla_base_distro == 'ubuntu' %} - +{% if placement_install_type == 'binary' and kolla_base_distro == 'ubuntu' %} + {% else %} - + {% endif %} Require all granted diff --git a/ansible/roles/placement/templates/placement-api.json.j2 b/ansible/roles/placement/templates/placement-api.json.j2 new file mode 100644 index 0000000000..14638509c5 --- /dev/null +++ b/ansible/roles/placement/templates/placement-api.json.j2 @@ -0,0 +1,42 @@ +{% set apache_binary = 'apache2' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd' %} +{% set apache_conf_dir = 'apache2/conf-enabled' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd/conf.d' %} +{ + "command": "/usr/sbin/{{ apache_binary }} -DFOREGROUND", + "config_files": [ + { + "source": "{{ container_config_directory }}/placement.conf", + "dest": "/etc/placement/placement.conf", + "owner": "placement", + "perm": "0600" + }{% if placement_policy_file is defined %}, + { + "source": "{{ container_config_directory }}/{{ placement_policy_file }}", + "dest": "/etc/placement/{{ placement_policy_file }}", + "owner": "placement", + "perm": "0600" + }{% endif %}, + { + "source": "{{ container_config_directory }}/placement-api-wsgi.conf", + "dest": "/etc/{{ apache_conf_dir }}/placement-api-wsgi.conf", + "owner": "placement", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/migrate-db.rc", + "dest": "/etc/placement/migrate-db.rc", + "owner": "placement", + "perm": "0600" + } + ], + "permissions": [ + { + "path": "/var/log/kolla/placement", + "owner": "placement:kolla", + "recurse": true + }, + { + "path": "/var/log/kolla/placement/placement.log", + "owner": "placement:placement" + } + ] +} diff --git a/ansible/roles/placement/templates/placement.conf.j2 b/ansible/roles/placement/templates/placement.conf.j2 new file mode 100644 index 0000000000..82f2575193 --- /dev/null +++ b/ansible/roles/placement/templates/placement.conf.j2 @@ -0,0 +1,61 @@ +[DEFAULT] +debug = {{ placement_logging_debug }} + +log_dir = /var/log/kolla/placement + +state_path = /var/lib/placement + +osapi_compute_listen = {{ api_interface_address }} + +# Though my_ip is not used directly, lots of other variables use $my_ip +my_ip = {{ api_interface_address }} + +transport_url = {{ rpc_transport_url }} + +[api] +use_forwarded_for = true + +[oslo_middleware] +enable_proxy_headers_parsing = True + +[oslo_concurrency] +lock_path = /var/lib/placement/tmp + +[placement_database] +connection = mysql+pymysql://{{ placement_database_user }}:{{ placement_database_password }}@{{ placement_database_address }}/{{ placement_database_name }} +max_pool_size = 50 +max_overflow = 1000 +max_retries = -1 + +[cache] +backend = oslo_cache.memcache_pool +enabled = True +memcache_servers = {% for host in groups['memcached'] %}{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ memcached_port }}{% if not loop.last %},{% endif %}{% endfor %} + + +[keystone_authtoken] +www_authenticate_uri = {{ keystone_internal_url }} +auth_url = {{ keystone_admin_url }} +auth_type = password +project_domain_id = {{ default_project_domain_id }} +user_domain_id = {{ default_user_domain_id }} +project_name = service +username = {{ placement_keystone_user }} +password = {{ placement_keystone_password }} + +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 %} + +{% if placement_policy_file is defined %} +[oslo_policy] +policy_file = {{ placement_policy_file }} +{% endif %} + +{% if enable_osprofiler | bool %} +[profiler] +enabled = true +trace_sqlalchemy = true +hmac_keys = {{ osprofiler_secret }} +connection_string = {{ osprofiler_backend_connection_string }} +{% endif %} diff --git a/ansible/site.yml b/ansible/site.yml index 5814e1b646..2344d4a0a5 100644 --- a/ansible/site.yml +++ b/ansible/site.yml @@ -65,6 +65,7 @@ - enable_openvswitch_{{ enable_openvswitch | bool }}_enable_ovs_dpdk_{{ enable_ovs_dpdk | bool }} - enable_outward_rabbitmq_{{ enable_outward_rabbitmq | bool }} - enable_panko_{{ enable_panko | bool }} + - enable_placement_{{ enable_placement | bool }} - enable_prometheus_{{ enable_prometheus | bool }} - enable_qdrouterd_{{ enable_qdrouterd | bool }} - enable_rabbitmq_{{ enable_rabbitmq | bool }} @@ -266,6 +267,10 @@ tasks_from: loadbalancer tags: neutron when: enable_neutron | bool + - include_role: + role: placement + tasks_from: loadbalancer + tags: placement - include_role: role: nova tasks_from: loadbalancer @@ -674,6 +679,17 @@ tags: cinder, when: enable_cinder | bool } +- name: Apply role placement + gather_facts: false + hosts: + - placement-api + - '&enable_placement_True' + serial: '{{ kolla_serial|default("0") }}' + roles: + - { role: placement, + tags: placement, + when: enable_placement | bool } + - name: Apply role nova gather_facts: false hosts: diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml index 264b6fcb79..a8d0ec9c2c 100644 --- a/etc/kolla/globals.yml +++ b/etc/kolla/globals.yml @@ -283,6 +283,7 @@ kolla_internal_vip_address: "10.10.10.254" #enable_ovs_dpdk: "no" #enable_osprofiler: "no" #enable_panko: "no" +#enable_placement: "{{ enable_nova }}" #enable_prometheus: "no" #enable_qdrouterd: "no" #enable_rally: "no" diff --git a/etc/kolla/passwords.yml b/etc/kolla/passwords.yml index 8d60d26180..beb9c86e1f 100644 --- a/etc/kolla/passwords.yml +++ b/etc/kolla/passwords.yml @@ -90,6 +90,7 @@ nova_api_database_password: nova_keystone_password: placement_keystone_password: +placement_database_password: neutron_database_password: neutron_keystone_password: diff --git a/tools/setup_gate.sh b/tools/setup_gate.sh index e022906df0..debea5e3c3 100755 --- a/tools/setup_gate.sh +++ b/tools/setup_gate.sh @@ -35,7 +35,7 @@ EOF rm ${PIP_CONF} if [[ $ACTION != "bifrost" ]]; then - GATE_IMAGES="cron,fluentd,glance,haproxy,keepalived,keystone,kolla-toolbox,mariadb,memcached,neutron,nova,openvswitch,rabbitmq,horizon,chrony,heat" + GATE_IMAGES="cron,fluentd,glance,haproxy,keepalived,keystone,kolla-toolbox,mariadb,memcached,neutron,nova,openvswitch,rabbitmq,horizon,chrony,heat,placement" else GATE_IMAGES="bifrost" fi