heat_template_version: rocky description: > OpenStack containerized Nova API service parameters: ContainerNovaApiImage: description: image type: string ContainerNovaConfigImage: description: The container image to use for the nova config_volume type: string NovaApiLoggingSource: type: json default: tag: openstack.nova.api file: /var/log/containers/nova/nova-api.log EndpointMap: default: {} description: Mapping of service endpoint -> protocol. Typically set via parameter_defaults in the resource registry. type: json ServiceData: default: {} description: Dictionary packing service data type: json ServiceNetMap: default: {} description: Mapping of service_name -> network name. Typically set via parameter_defaults in the resource registry. This mapping overrides those in ServiceNetMapDefaults. type: json DefaultPasswords: default: {} type: json RoleName: default: '' description: Role name on which the service is applied type: string RoleParameters: default: {} description: Parameters specific to the role type: json DeployIdentifier: default: '' type: string description: > Setting this to a unique value will re-run any deployment tasks which perform configuration on a Heat stack-update. EnableInternalTLS: type: boolean default: false NovaDbSyncTimeout: default: 300 description: Timeout for Nova db sync type: number NovaPassword: description: The password for the nova service and db account type: string hidden: true MysqlIPv6: default: false description: Enable IPv6 in MySQL type: boolean NovaWorkers: default: 0 description: Number of workers for Nova services. type: number KeystoneRegion: type: string default: 'regionOne' description: Keystone region for endpoint NeutronMetadataProxySharedSecret: description: Shared secret to prevent spoofing type: string hidden: true InstanceNameTemplate: default: 'instance-%08x' description: Template string to be used to generate instance names type: string NovaEnableDBPurge: default: true description: | Whether to create cron job for purging soft deleted rows in Nova database. type: boolean NovaEnableDBArchive: default: true description: | Whether to create cron job for archiving soft deleted rows in Nova database. type: boolean MonitoringSubscriptionNovaApi: default: 'overcloud-nova-api' type: string NovaDefaultFloatingPool: default: 'public' description: Default pool for floating IP addresses type: string NovaApiPolicies: description: | A hash of policies to configure for Nova API. e.g. { nova-context_is_admin: { key: context_is_admin, value: 'role:admin' } } default: {} type: json parameter_groups: - label: deprecated description: | The following parameters are deprecated and will be removed. They should not be relied on for new deployments. If you have concerns regarding deprecated parameters, please contact the TripleO development team on IRC or the OpenStack mailing list. parameters: - MysqlIPv6 conditions: internal_tls_enabled: {equals: [{get_param: EnableInternalTLS}, true]} mysql_ipv6_use_ip_address: and: - {equals: [{get_param: [ServiceData, net_ip_version_map, {get_param: [ServiceNetMap, MysqlNetwork]}]}, 6]} - {equals: [{get_param: EnableInternalTLS}, false]} nova_workers_zero: {equals : [{get_param: NovaWorkers}, 0]} is_neutron_shared_metadata_notempty: {not: {equals: [{get_param: NeutronMetadataProxySharedSecret}, '']}} resources: ContainersCommon: type: ../containers-common.yaml MySQLClient: type: ../../deployment/database/mysql-client.yaml NovaApiLogging: type: OS::TripleO::Services::Logging::NovaApi ApacheServiceBase: type: ../../deployment/apache/apache-baremetal-puppet.yaml properties: ServiceData: {get_param: ServiceData} ServiceNetMap: {get_param: ServiceNetMap} DefaultPasswords: {get_param: DefaultPasswords} EndpointMap: {get_param: EndpointMap} RoleName: {get_param: RoleName} RoleParameters: {get_param: RoleParameters} EnableInternalTLS: {get_param: EnableInternalTLS} NovaBase: type: ./nova-base-puppet.yaml properties: ServiceData: {get_param: ServiceData} ServiceNetMap: {get_param: ServiceNetMap} DefaultPasswords: {get_param: DefaultPasswords} EndpointMap: {get_param: EndpointMap} RoleName: {get_param: RoleName} RoleParameters: {get_param: RoleParameters} outputs: role_data: description: Role data for the Nova API role. value: service_name: nova_api firewall_rules: '113 nova_api': dport: - 8774 - 13774 keystone_resources: nova: endpoints: public: {get_param: [EndpointMap, NovaPublic, uri]} internal: {get_param: [EndpointMap, NovaInternal, uri]} admin: {get_param: [EndpointMap, NovaAdmin, uri]} users: nova: roles: - admin - service password: {get_param: NovaPassword} region: {get_param: KeystoneRegion} service: 'compute' monitoring_subscription: {get_param: MonitoringSubscriptionNovaApi} config_settings: map_merge: - get_attr: [NovaBase, role_data, config_settings] - get_attr: [NovaApiLogging, config_settings] - apache::default_vhost: false nova::keystone::authtoken::project_name: 'service' nova::keystone::authtoken::user_domain_name: 'Default' nova::keystone::authtoken::project_domain_name: 'Default' nova::keystone::authtoken::password: {get_param: NovaPassword} nova::keystone::authtoken::www_authenticate_uri: {get_param: [EndpointMap, KeystoneInternal, uri_no_suffix] } nova::keystone::authtoken::auth_url: {get_param: [EndpointMap, KeystoneInternal, uri_no_suffix]} nova::keystone::authtoken::region_name: {get_param: KeystoneRegion} nova::api::enabled: true nova::api::default_floating_pool: {get_param: NovaDefaultFloatingPool} nova::api::sync_db_api: true nova::api::enable_proxy_headers_parsing: true nova::api::api_bind_address: str_replace: template: "%{hiera('fqdn_$NETWORK')}" params: $NETWORK: {get_param: [ServiceNetMap, NovaApiNetwork]} nova::api::service_name: 'httpd' nova::wsgi::apache_api::ssl: {get_param: EnableInternalTLS} # NOTE: bind IP is found in hiera replacing the network name with the local node IP # for the given network; replacement examples (eg. for internal_api): # internal_api -> IP # internal_api_uri -> [IP] # internal_api_subnet - > IP/CIDR nova::wsgi::apache_api::bind_host: str_replace: template: "%{hiera('$NETWORK')}" params: $NETWORK: {get_param: [ServiceNetMap, NovaApiNetwork]} nova::wsgi::apache_api::servername: str_replace: template: "%{hiera('fqdn_$NETWORK')}" params: $NETWORK: {get_param: [ServiceNetMap, NovaApiNetwork]} nova::api::instance_name_template: {get_param: InstanceNameTemplate} nova_enable_db_purge: {get_param: NovaEnableDBPurge} nova_enable_db_archive: {get_param: NovaEnableDBArchive} nova::policy::policies: {get_param: NovaApiPolicies} - if: - nova_workers_zero - {} - nova::api::osapi_compute_workers: {get_param: NovaWorkers} nova::wsgi::apache_api::workers: {get_param: NovaWorkers} - if: - is_neutron_shared_metadata_notempty - nova::api::neutron_metadata_proxy_shared_secret: {get_param: NeutronMetadataProxySharedSecret} - {} service_config_settings: rsyslog: tripleo_logging_sources_nova_api: - {get_param: NovaApiLoggingSource} mysql: map_merge: - {get_attr: [NovaBase, role_data, service_config_settings, mysql]} - nova::db::mysql_api::password: {get_param: NovaPassword} nova::db::mysql_api::user: nova_api nova::db::mysql_api::host: {get_param: [EndpointMap, MysqlInternal, host_nobrackets]} nova::db::mysql_api::dbname: nova_api nova::db::mysql_api::allowed_hosts: - '%' - "%{hiera('mysql_bind_host')}" # BEGIN DOCKER SETTINGS puppet_config: config_volume: nova puppet_tags: nova_config step_config: list_join: - "\n" - - "['Nova_cell_v2'].each |String $val| { noop_resource($val) }" - include tripleo::profile::base::nova::api - {get_attr: [MySQLClient, role_data, step_config]} config_image: {get_param: ContainerNovaConfigImage} kolla_config: /var/lib/kolla/config_files/nova_api.json: command: /usr/sbin/httpd -DFOREGROUND config_files: - source: "/var/lib/kolla/config_files/src/etc/httpd/conf.d" dest: "/etc/httpd/conf.d" merge: false preserve_properties: true - source: "/var/lib/kolla/config_files/src/*" dest: "/" merge: true preserve_properties: true permissions: - path: /var/log/nova owner: nova:nova recurse: true /var/lib/kolla/config_files/nova_api_cron.json: command: /usr/sbin/crond -n config_files: - source: "/var/lib/kolla/config_files/src/*" dest: "/" merge: true preserve_properties: true permissions: - path: /var/log/nova owner: nova:nova recurse: true container_config_scripts: map_merge: - {get_attr: [ContainersCommon, container_config_scripts]} - nova_wait_for_api_service.py: mode: "0755" content: { get_file: ../../container_config_scripts/nova_wait_for_api_service.py } nova_api_ensure_default_cell.sh: mode: "0700" content: str_replace: template: | #!/bin/bash DEFID=$(su nova -s /bin/bash -c "nova-manage cell_v2 list_cells" | sed -e '1,3d' -e '$d' | awk -F ' *| *' '$2 == "default" {print $4}') if [ "$DEFID" ]; then echo "(cellv2) Updating default cell_v2 cell $DEFID" su nova -s /bin/bash -c "/usr/bin/nova-manage cell_v2 update_cell --cell_uuid $DEFID --name=default --database_connection='CELLDB' --transport-url='TRANSPORTURL'" else echo "(cellv2) Creating default cell_v2 cell" su nova -s /bin/bash -c "/usr/bin/nova-manage cell_v2 create_cell --name=default --database_connection='CELLDB' --transport-url='TRANSPORTURL'" fi params: CELLDB: list_join: - '' - - '{scheme}' - '://' - '{username}' - ':' - '{password}' - '@' - if: - mysql_ipv6_use_ip_address - '[{hostname}]' - '{hostname}' - '/' - 'nova' - '?' - '{query}' TRANSPORTURL: list_join: - '' - - '{scheme}' - '://' - '{username}' - ':' - '{password}' - '@' - '{hostname}' - ':' - '{port}' - '/' - '?' - '{query}' docker_config: step_2: get_attr: [NovaApiLogging, docker_config, step_2] step_3: nova_api_db_sync: start_order: 0 # Runs before nova-conductor dbsync image: &nova_api_image {get_param: ContainerNovaApiImage} net: host detach: false user: root volumes: &nova_api_bootstrap_volumes list_concat: - {get_attr: [ContainersCommon, volumes]} - {get_attr: [NovaApiLogging, volumes]} - - /var/lib/config-data/nova/etc/my.cnf.d/tripleo.cnf:/etc/my.cnf.d/tripleo.cnf:ro - /var/lib/config-data/nova/etc/nova/:/etc/nova/:ro command: "/usr/bin/bootstrap_host_exec nova_api su nova -s /bin/bash -c '/usr/bin/nova-manage api_db sync'" environment: TRIPLEO_DEPLOY_IDENTIFIER: {get_param: DeployIdentifier} nova_api_map_cell0: start_order: 1 # Runs before nova-conductor dbsync image: *nova_api_image net: host detach: false user: root volumes: *nova_api_bootstrap_volumes command: str_replace: template: "/usr/bin/bootstrap_host_exec nova_api su nova -s /bin/bash -c '/usr/bin/nova-manage cell_v2 map_cell0 --database_connection=\"CELL0DB\"'" params: CELL0DB: list_join: - '' - - '{scheme}' - '://' - '{username}' - ':' - '{password}' - '@' - if: - mysql_ipv6_use_ip_address - '[{hostname}]' - '{hostname}' - '/' - 'nova_cell0' - '?' - '{query}' nova_api_ensure_default_cell: start_order: 2 # Runs before nova-conductor dbsync image: *nova_api_image net: host detach: false volumes: list_concat: - *nova_api_bootstrap_volumes - - /var/lib/config-data/puppet-generated/nova:/var/lib/kolla/config_files/src:ro - /var/lib/container-config-scripts/nova_api_ensure_default_cell.sh:/nova_api_ensure_default_cell.sh:ro user: root command: "/usr/bin/bootstrap_host_exec nova_api /nova_api_ensure_default_cell.sh" step_4: nova_api: start_order: 2 image: *nova_api_image net: host user: root privileged: false restart: always healthcheck: test: /openstack/healthcheck volumes: list_concat: - {get_attr: [ContainersCommon, volumes]} - {get_attr: [NovaApiLogging, volumes]} - - /var/lib/kolla/config_files/nova_api.json:/var/lib/kolla/config_files/config.json:ro - /var/lib/config-data/puppet-generated/nova:/var/lib/kolla/config_files/src:ro - if: - internal_tls_enabled - - /etc/pki/tls/certs/httpd:/etc/pki/tls/certs/httpd:ro - [] - if: - internal_tls_enabled - - /etc/pki/tls/private/httpd:/etc/pki/tls/private/httpd:ro - [] environment: KOLLA_CONFIG_STRATEGY: COPY_ALWAYS nova_wait_for_api_service: start_order: 3 image: *nova_api_image user: root net: host privileged: false detach: false volumes: list_concat: - {get_attr: [ContainersCommon, volumes]} - - /var/lib/config-data/nova/etc/my.cnf.d/:/etc/my.cnf.d/:ro - /var/lib/config-data/nova/etc/nova/:/etc/nova/:ro - /var/log/containers/nova:/var/log/nova - /var/lib/container-config-scripts/:/container-config-scripts/:z command: "/usr/bin/bootstrap_host_exec nova_api su nova -s /bin/bash -c '/container-config-scripts/pyshim.sh /container-config-scripts/nova_wait_for_api_service.py'" environment: __OS_DEBUG: yaql: expression: str($.data.debug) data: debug: {get_attr: [NovaBase, role_data, config_settings, 'nova::logging::debug']} nova_api_cron: start_order: 4 image: *nova_api_image net: host user: root privileged: false restart: always healthcheck: test: '/usr/share/openstack-tripleo-common/healthcheck/cron nova' volumes: list_concat: - {get_attr: [ContainersCommon, volumes]} - {get_attr: [NovaApiLogging, volumes]} - - /var/lib/kolla/config_files/nova_api_cron.json:/var/lib/kolla/config_files/config.json:ro - /var/lib/config-data/puppet-generated/nova:/var/lib/kolla/config_files/src:ro environment: KOLLA_CONFIG_STRATEGY: COPY_ALWAYS metadata_settings: get_attr: [ApacheServiceBase, role_data, metadata_settings] deploy_steps_tasks: - name: validate nova-api container state podman_container_info: name: nova_api register: nova_api_infos failed_when: - nova_api_infos.containers.0.Healthcheck.Status is defined - "'healthy' not in nova_api_infos.containers.0.Healthcheck.Status" retries: 10 delay: 30 tags: - opendev-validation - opendev-validation-nova when: - container_cli == 'podman' - not container_healthcheck_disabled - step|int == 4 host_prep_tasks: {get_attr: [NovaApiLogging, host_prep_tasks]} external_upgrade_tasks: - when: step|int == 1 block: - name: Online data migration for Nova command: "{{ container_cli }} exec nova_api nova-manage db online_data_migrations" delegate_to: "{{ groups['nova_api'][0] }}" become: true tags: - online_upgrade - online_upgrade_nova - when: - step|int == 1 tags: - never - system_upgrade_transfer_data - system_upgrade_stop_services block: - name: Stop nova api container import_role: name: tripleo_container_stop vars: tripleo_containers_to_stop: - nova_api - nova_api_cron tripleo_delegate_to: "{{ groups['nova_api'] | default([]) }}" fast_forward_upgrade_tasks: - when: - step|int == 0 - release == 'rocky' block: - name: Check if nova-api is deployed command: systemctl is-enabled --quiet openstack-nova-api failed_when: false register: nova_api_enabled_result - name: Set fact nova_api_enabled set_fact: nova_api_enabled: "{{ nova_api_enabled_result.rc == 0 }}" - name: Stop openstack-nova-api service service: name=openstack-nova-api state=stopped when: - step|int == 1 - nova_api_enabled|bool - release == 'rocky' - name: Extra migration for nova tripleo/+bug/1656791 command: nova-manage db online_data_migrations when: - step|int == 5 - release == 'rocky' - is_bootstrap_node|bool - name: Update nova packages package: name: '*nova*' state: latest when: - step|int == 6 - is_bootstrap_node|bool #FIXME(lyarwood): Use puppet to do this? - when: - step|int == 7 - release == 'rocky' - is_bootstrap_node|bool block: - name: Create puppet manifest to set transport_url in nova.conf copy: dest: /root/nova-api_upgrade_manifest.pp mode: 0600 content: > $transport_url = os_transport_url({ 'transport' => hiera('messaging_service_name', 'rabbit'), 'hosts' => any2array(hiera('rabbitmq_node_names', undef)), 'port' => sprintf('%s',hiera('nova::rabbit_port', '5672') ), 'username' => hiera('nova::rabbit_userid', 'guest'), 'password' => hiera('nova::rabbit_password'), 'ssl' => sprintf('%s', bool2num(str2bool(hiera('nova::rabbit_use_ssl', '0')))) }) oslo::messaging::default { 'nova_config': transport_url => $transport_url } - name: Run puppet apply to set tranport_url in nova.conf command: puppet apply --modulepath /etc/puppet/modules:/opt/stack/puppet-modules:/usr/share/openstack-puppet/modules --detailed-exitcodes /root/nova-api_upgrade_manifest.pp register: puppet_apply_nova_api_upgrade failed_when: puppet_apply_nova_api_upgrade.rc not in [0,2] changed_when: puppet_apply_nova_api_upgrade.rc == 2 - name: Setup cell_v2 (map cell0) shell: str_replace: template: nova-manage cell_v2 map_cell0 --database_connection='CELL0DB' --transport-url="'TRANSPORTURL'" params: CELL0DB: list_join: - '' - - '{scheme}' - '://' - '{username}' - ':' - '{password}' - '@' - if: - mysql_ipv6_use_ip_address - '[{hostname}]' - '{hostname}' - '/' - 'nova_cell0' - '?' - '{query}' TRANSPORTURL: list_join: - '' - - '{scheme}' - '://' - '{username}' - ':' - '{password}' - '@' - '{hostname}' - ':' - '{port}' - '/' - '?' - '{query}' - name: Setup cell_v2 (create default cell) # (owalsh) puppet-nova expects the cell name 'default' shell: str_replace: template: nova-manage cell_v2 create_cell --name='default' --database_connection='CELLDB' params: CELLDB: list_join: - '' - - '{scheme}' - '://' - '{username}' - ':' - '{password}' - '@' - if: - mysql_ipv6_use_ip_address - '[{hostname}]' - '{hostname}' - '/' - 'nova' - '?' - '{query}' register: nova_api_create_cell failed_when: nova_api_create_cell.rc not in [0,2] changed_when: nova_api_create_cell.rc == 0 - name: Setup cell_v2 (sync nova/cell DB) command: nova-manage db sync async: {get_param: NovaDbSyncTimeout} poll: 10 - name: Setup cell_v2 (get cell uuid) shell: nova-manage cell_v2 list_cells | sed -e '1,3d' -e '$d' | awk -F ' *| *' '$2 == "default" {print $4}' register: nova_api_cell_uuid - name: Setup cell_v2 (migrate hosts) command: nova-manage cell_v2 discover_hosts --cell_uuid {{nova_api_cell_uuid.stdout}} --verbose - name: Setup cell_v2 (migrate instances) command: nova-manage cell_v2 map_instances --cell_uuid {{nova_api_cell_uuid.stdout}} - when: - step|int == 8 - is_bootstrap_node|bool block: - name: Sync nova/cell DB command: nova-manage db sync async: {get_param: NovaDbSyncTimeout} poll: 10 when: - release == 'stein' - name: Sync nova_api DB command: nova-manage api_db sync - name: Online data migration for nova command: nova-manage db online_data_migrations