<commit_before>heat_template_version: wallaby

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. Use
                 parameter_merge_strategies to merge it with the defaults.
    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
  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
  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
  NovaAllowResizeToSameHost:
    default: false
    description: Allow destination machine to match source for resize.
    type: boolean
  NovaApiMaxLimit:
    default: 1000
    description: Max number of objects returned per API query
    type: number
  NovaCronPurgeShadowTablesMinute:
    type: string
    description: >
        Cron to purge shadow tables - Minute
    default: '0'
  NovaCronPurgeShadowTablesHour:
    type: string
    description: >
        Cron to purge shadow tables - Hour
    default: '5'
  NovaCronPurgeShadowTablesMonthday:
    type: string
    description: >
        Cron to purge shadow tables - Month Day
    default: '*'
  NovaCronPurgeShadowTablesMonth:
    type: string
    description: >
        Cron to purge shadow tables - Month
    default: '*'
  NovaCronPurgeShadowTablesWeekday:
    type: string
    description: >
        Cron to purge shadow tables - Week Day
    default: '*'
  NovaCronPurgeShadowTablesUser:
    type: string
    description: >
        Cron to purge shadow tables - User
    default: 'nova'
  NovaCronPurgeShadowTablesDestination:
    type: string
    description: >
        Cron to purge shadow tables - Log destination
    default: '/var/log/nova/nova-rowspurge.log'
  NovaCronPurgeShadowTablesMaxDelay:
    type: string
    description: >
        Cron to purge shadow tables - Max Delay
    default: '3600'
  NovaCronPurgeShadowTablesAge:
    type: number
    description: >
        Cron to purge shadow tables - Age
        This will define the retention policy when
        purging the shadow tables in days.
        0 means, purge data older than today in
        shadow tables.
    default: 14
  NovaCronPurgeShadowTablesVerbose:
    type: boolean
    description: >
        Cron to purge shadow tables - Verbose
    default: false
  NovaCronPurgeShadowTablesAllCells:
    type: boolean
    description: >
        Cron to purge shadow tables - All cells
    default: true
  NovaCronArchiveDeleteRowsMinute:
    type: string
    description: >
        Cron to move deleted instances to another table - Minute
    default: '1'
  NovaCronArchiveDeleteRowsHour:
    type: string
    description: >
        Cron to move deleted instances to another table - Hour
    default: '0'
  NovaCronArchiveDeleteRowsMonthday:
    type: string
    description: >
        Cron to move deleted instances to another table - Month Day
    default: '*'
  NovaCronArchiveDeleteRowsMonth:
    type: string
    description: >
        Cron to move deleted instances to another table - Month
    default: '*'
  NovaCronArchiveDeleteRowsWeekday:
    type: string
    description: >
        Cron to move deleted instances to another table - Week Day
    default: '*'
  NovaCronArchiveDeleteRowsMaxRows:
    type: string
    description: >
        Cron to move deleted instances to another table - Max Rows
    default: '1000'
  NovaCronArchiveDeleteRowsUser:
    type: string
    description: >
        Cron to move deleted instances to another table - User
    default: 'nova'
  NovaCronArchiveDeleteRowsDestination:
    type: string
    description: >
        Cron to move deleted instances to another table - Log destination
    default: '/var/log/nova/nova-rowsflush.log'
  NovaCronArchiveDeleteRowsMaxDelay:
    type: string
    description: >
        Cron to move deleted instances to another table - Max Delay
    default: '3600'
  NovaCronArchiveDeleteRowsUntilComplete:
    type: boolean
    description: >
        Cron to move deleted instances to another table - Until complete
    default: true
  NovaCronArchiveDeleteRowsPurge:
    type: boolean
    description: >
        Purge shadow tables immediately after scheduled archiving
    default: false
  NovaCronArchiveDeleteAllCells:
    type: boolean
    description: >
        Archive deleted instances from all cells
    default: true
  NovaCronArchiveDeleteRowsAge:
    type: number
    description: >
        Cron to archive deleted instances - Age
        This will define the retention policy when
        archiving the deleted instances entries in days.
        0 means, purge data older than today in
        shadow tables.
    default: 90
  NovaCronArchiveDeleteRowsTaskLog:
    type: boolean
    description: >
        Archive task_log records while archiving the database
    default: true
  MemcacheUseAdvancedPool:
    type: boolean
    description: |
      Use the advanced (eventlet safe) memcached client pool.
    default: true

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:
  mysql_ipv6_use_ip_address:
    and:
    - {equals: [{get_param: [ServiceData, net_ip_version_map, {get_param: [ServiceNetMap, MysqlNetwork]}]}, 6]}
    - not: {get_param: EnableInternalTLS}
  nova_workers_set:
    not: {equals : [{get_param: NovaWorkers}, 0]}

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}
      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}
      EndpointMap: {get_param: EndpointMap}
      RoleName: {get_param: RoleName}
      RoleParameters: {get_param: RoleParameters}

  NovaApiDBClient:
    type: ./nova-apidb-client-puppet.yaml
    properties:
      ServiceData: {get_param: ServiceData}
      ServiceNetMap: {get_param: ServiceNetMap}
      EndpointMap: {get_param: EndpointMap}
      RoleName: {get_param: RoleName}
      RoleParameters: {get_param: RoleParameters}

  NovaDBClient:
    type: ./nova-db-client-puppet.yaml
    properties:
      ServiceData: {get_param: ServiceData}
      ServiceNetMap: {get_param: ServiceNetMap}
      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: [NovaApiDBClient, role_data, config_settings]
          - get_attr: [NovaDBClient, 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::keystone::authtoken::interface: 'internal'
            nova::keystone::authtoken::memcache_use_advanced_pool: {get_param: MemcacheUseAdvancedPool}
            nova::api::max_limit: {get_param: NovaApiMaxLimit}
            nova::api::enabled: true
            nova::network::neutron::default_floating_pool: {get_param: NovaDefaultFloatingPool}
            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::policy::policies: {get_param: NovaApiPolicies}
            nova::api::allow_resize_to_same_host: {get_param: NovaAllowResizeToSameHost}
            nova_enable_db_purge: {get_param: NovaEnableDBPurge}
            nova::cron::purge_shadow_tables::minute: {get_param: NovaCronPurgeShadowTablesMinute}
            nova::cron::purge_shadow_tables::hour: {get_param: NovaCronPurgeShadowTablesHour}
            nova::cron::purge_shadow_tables::monthday: {get_param: NovaCronPurgeShadowTablesMonthday}
            nova::cron::purge_shadow_tables::month: {get_param: NovaCronPurgeShadowTablesMonth}
            nova::cron::purge_shadow_tables::weekday: {get_param: NovaCronPurgeShadowTablesWeekday}
            nova::cron::purge_shadow_tables::user: {get_param: NovaCronPurgeShadowTablesUser}
            nova::cron::purge_shadow_tables::destination: {get_param: NovaCronPurgeShadowTablesDestination}
            nova::cron::purge_shadow_tables::maxdelay: {get_param: NovaCronPurgeShadowTablesMaxDelay}
            nova::cron::purge_shadow_tables::age: {get_param: NovaCronPurgeShadowTablesAge}
            nova::cron::purge_shadow_tables::verbose: {get_param: NovaCronPurgeShadowTablesVerbose}
            nova::cron::purge_shadow_tables::all_cells: {get_param: NovaCronPurgeShadowTablesAllCells}
            nova_enable_db_archive: {get_param: NovaEnableDBArchive}
            nova::cron::archive_deleted_rows::minute: {get_param: NovaCronArchiveDeleteRowsMinute}
            nova::cron::archive_deleted_rows::hour: {get_param: NovaCronArchiveDeleteRowsHour}
            nova::cron::archive_deleted_rows::monthday: {get_param: NovaCronArchiveDeleteRowsMonthday}
            nova::cron::archive_deleted_rows::month: {get_param: NovaCronArchiveDeleteRowsMonth}
            nova::cron::archive_deleted_rows::weekday: {get_param: NovaCronArchiveDeleteRowsWeekday}
            nova::cron::archive_deleted_rows::max_rows: {get_param: NovaCronArchiveDeleteRowsMaxRows}
            nova::cron::archive_deleted_rows::user: {get_param: NovaCronArchiveDeleteRowsUser}
            nova::cron::archive_deleted_rows::destination: {get_param: NovaCronArchiveDeleteRowsDestination}
            nova::cron::archive_deleted_rows::maxdelay: {get_param: NovaCronArchiveDeleteRowsMaxDelay}
            nova::cron::archive_deleted_rows::until_complete: {get_param: NovaCronArchiveDeleteRowsUntilComplete}
            nova::cron::archive_deleted_rows::purge: {get_param: NovaCronArchiveDeleteRowsPurge}
            nova::cron::archive_deleted_rows::all_cells: {get_param: NovaCronArchiveDeleteAllCells}
            nova::cron::archive_deleted_rows::age: {get_param: NovaCronArchiveDeleteRowsAge}
            nova::cron::archive_deleted_rows::task_log: {get_param: NovaCronArchiveDeleteRowsTaskLog}
          - if:
            - nova_workers_set
            - nova::api::osapi_compute_workers: {get_param: NovaWorkers}
              nova::wsgi::apache_api::workers: {get_param: NovaWorkers}
      service_config_settings:
        rabbitmq: {get_attr: [NovaBase, role_data, service_config_settings], rabbitmq}
        mysql:
          map_merge:
            - get_attr: [NovaApiDBClient, role_data, service_config_settings, mysql]
            - get_attr: [NovaDBClient, role_data, service_config_settings, mysql]
        rsyslog:
          tripleo_logging_sources_nova_api:
            - {get_param: NovaApiLoggingSource}
      # 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: &nova_api_db_sync
            - 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/etc/httpd/conf.modules.d"
              dest: "/etc/httpd/conf.modules.d"
              merge: false
              preserve_properties: true
            - source: "/var/lib/kolla/config_files/src/*"
              dest: "/"
              merge: true
              preserve_properties: true
          permissions: &nova_api_permissions
            - path: /var/log/nova
              owner: nova:nova
              recurse: true
        /var/lib/kolla/config_files/nova_api_db_sync.json:
          command: "/usr/bin/bootstrap_host_exec nova_api su nova -s /bin/bash -c '/usr/bin/nova-manage api_db sync'"
          config_files: *nova_api_db_sync
          permissions: *nova_api_permissions
        /var/lib/kolla/config_files/nova_api_map_cell0.json:
          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}'
          config_files: *nova_api_db_sync
          permissions: *nova_api_permissions
        /var/lib/kolla/config_files/nova_api_ensure_default_cell.json:
          command: "/usr/bin/bootstrap_host_exec nova_api /nova_api_ensure_default_cell.sh"
          config_files: *nova_api_db_sync
          permissions: *nova_api_permissions
        /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: *nova_api_permissions
        /var/lib/kolla/config_files/nova_wait_for_api_service.json:
          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'"
          config_files: *nova_api_db_sync
          permissions: *nova_api_permissions

      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:
              list_concat:
                - {get_attr: [ContainersCommon, volumes]}
                - {get_attr: [NovaApiLogging, volumes]}
                - - /var/lib/kolla/config_files/nova_api_db_sync.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
              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:
              list_concat:
                - {get_attr: [ContainersCommon, volumes]}
                - {get_attr: [NovaApiLogging, volumes]}
                - - /var/lib/kolla/config_files/nova_api_map_cell0.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
          nova_api_ensure_default_cell:
            start_order: 2 # Runs before nova-conductor dbsync
            image: *nova_api_image
            net: host
            detach: false
            volumes:
              list_concat:
                - {get_attr: [ContainersCommon, volumes]}
                - {get_attr: [NovaApiLogging, volumes]}
                - - /var/lib/kolla/config_files/nova_api_ensure_default_cell.json:/var/lib/kolla/config_files/config.json:ro
                  - /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
            environment:
              KOLLA_CONFIG_STRATEGY: COPY_ALWAYS
        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:
                    - {get_param: EnableInternalTLS}
                    - - /etc/pki/tls/certs/httpd:/etc/pki/tls/certs/httpd:ro
                      - /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]}
                - {get_attr: [NovaApiLogging, volumes]}
                - - /var/lib/kolla/config_files/nova_wait_for_api_service.json:/var/lib/kolla/config_files/config.json:ro
                  - /var/lib/config-data/puppet-generated/nova:/var/lib/kolla/config_files/src:ro
                  - /var/lib/container-config-scripts/:/container-config-scripts/:z
            environment:
              __OS_DEBUG:
                yaql:
                  expression: str($.data.debug)
                  data:
                    debug: {get_attr: [NovaBase, role_data, config_settings, 'nova::logging::debug']}
              KOLLA_CONFIG_STRATEGY: COPY_ALWAYS
          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:
        list_concat:
          - get_attr: [ApacheServiceBase, role_data, deploy_steps_tasks]
          - - name: validate nova-api container state
              containers.podman.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
          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([]) }}"
<commit_msg>Allow configuring secure RBAC in nova<commit_after>heat_template_version: wallaby

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. Use
                 parameter_merge_strategies to merge it with the defaults.
    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
  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
  EnforceSecureRbac:
    type: boolean
    default: false
    description: >-
      Setting this option to True will configure each OpenStack service to
      enforce Secure RBAC by setting `[oslo_policy] enforce_new_defaults` and
      `[oslo_policy] enforce_scope` to True. This introduces a consistent set
      of RBAC personas across OpenStack services that include support for
      system and project scope, as well as keystone's default roles, admin,
      member, and reader. Do not enable this functionality until all services in
      your deployment actually support secure RBAC.
  KeystoneRegion:
    type: string
    default: 'regionOne'
    description: Keystone region for endpoint
  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
  NovaAllowResizeToSameHost:
    default: false
    description: Allow destination machine to match source for resize.
    type: boolean
  NovaApiMaxLimit:
    default: 1000
    description: Max number of objects returned per API query
    type: number
  NovaCronPurgeShadowTablesMinute:
    type: string
    description: >
        Cron to purge shadow tables - Minute
    default: '0'
  NovaCronPurgeShadowTablesHour:
    type: string
    description: >
        Cron to purge shadow tables - Hour
    default: '5'
  NovaCronPurgeShadowTablesMonthday:
    type: string
    description: >
        Cron to purge shadow tables - Month Day
    default: '*'
  NovaCronPurgeShadowTablesMonth:
    type: string
    description: >
        Cron to purge shadow tables - Month
    default: '*'
  NovaCronPurgeShadowTablesWeekday:
    type: string
    description: >
        Cron to purge shadow tables - Week Day
    default: '*'
  NovaCronPurgeShadowTablesUser:
    type: string
    description: >
        Cron to purge shadow tables - User
    default: 'nova'
  NovaCronPurgeShadowTablesDestination:
    type: string
    description: >
        Cron to purge shadow tables - Log destination
    default: '/var/log/nova/nova-rowspurge.log'
  NovaCronPurgeShadowTablesMaxDelay:
    type: string
    description: >
        Cron to purge shadow tables - Max Delay
    default: '3600'
  NovaCronPurgeShadowTablesAge:
    type: number
    description: >
        Cron to purge shadow tables - Age
        This will define the retention policy when
        purging the shadow tables in days.
        0 means, purge data older than today in
        shadow tables.
    default: 14
  NovaCronPurgeShadowTablesVerbose:
    type: boolean
    description: >
        Cron to purge shadow tables - Verbose
    default: false
  NovaCronPurgeShadowTablesAllCells:
    type: boolean
    description: >
        Cron to purge shadow tables - All cells
    default: true
  NovaCronArchiveDeleteRowsMinute:
    type: string
    description: >
        Cron to move deleted instances to another table - Minute
    default: '1'
  NovaCronArchiveDeleteRowsHour:
    type: string
    description: >
        Cron to move deleted instances to another table - Hour
    default: '0'
  NovaCronArchiveDeleteRowsMonthday:
    type: string
    description: >
        Cron to move deleted instances to another table - Month Day
    default: '*'
  NovaCronArchiveDeleteRowsMonth:
    type: string
    description: >
        Cron to move deleted instances to another table - Month
    default: '*'
  NovaCronArchiveDeleteRowsWeekday:
    type: string
    description: >
        Cron to move deleted instances to another table - Week Day
    default: '*'
  NovaCronArchiveDeleteRowsMaxRows:
    type: string
    description: >
        Cron to move deleted instances to another table - Max Rows
    default: '1000'
  NovaCronArchiveDeleteRowsUser:
    type: string
    description: >
        Cron to move deleted instances to another table - User
    default: 'nova'
  NovaCronArchiveDeleteRowsDestination:
    type: string
    description: >
        Cron to move deleted instances to another table - Log destination
    default: '/var/log/nova/nova-rowsflush.log'
  NovaCronArchiveDeleteRowsMaxDelay:
    type: string
    description: >
        Cron to move deleted instances to another table - Max Delay
    default: '3600'
  NovaCronArchiveDeleteRowsUntilComplete:
    type: boolean
    description: >
        Cron to move deleted instances to another table - Until complete
    default: true
  NovaCronArchiveDeleteRowsPurge:
    type: boolean
    description: >
        Purge shadow tables immediately after scheduled archiving
    default: false
  NovaCronArchiveDeleteAllCells:
    type: boolean
    description: >
        Archive deleted instances from all cells
    default: true
  NovaCronArchiveDeleteRowsAge:
    type: number
    description: >
        Cron to archive deleted instances - Age
        This will define the retention policy when
        archiving the deleted instances entries in days.
        0 means, purge data older than today in
        shadow tables.
    default: 90
  NovaCronArchiveDeleteRowsTaskLog:
    type: boolean
    description: >
        Archive task_log records while archiving the database
    default: true
  MemcacheUseAdvancedPool:
    type: boolean
    description: |
      Use the advanced (eventlet safe) memcached client pool.
    default: true

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:
  mysql_ipv6_use_ip_address:
    and:
    - {equals: [{get_param: [ServiceData, net_ip_version_map, {get_param: [ServiceNetMap, MysqlNetwork]}]}, 6]}
    - not: {get_param: EnableInternalTLS}
  nova_workers_set:
    not: {equals : [{get_param: NovaWorkers}, 0]}

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}
      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}
      EndpointMap: {get_param: EndpointMap}
      RoleName: {get_param: RoleName}
      RoleParameters: {get_param: RoleParameters}

  NovaApiDBClient:
    type: ./nova-apidb-client-puppet.yaml
    properties:
      ServiceData: {get_param: ServiceData}
      ServiceNetMap: {get_param: ServiceNetMap}
      EndpointMap: {get_param: EndpointMap}
      RoleName: {get_param: RoleName}
      RoleParameters: {get_param: RoleParameters}

  NovaDBClient:
    type: ./nova-db-client-puppet.yaml
    properties:
      ServiceData: {get_param: ServiceData}
      ServiceNetMap: {get_param: ServiceNetMap}
      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: [NovaApiDBClient, role_data, config_settings]
          - get_attr: [NovaDBClient, 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::keystone::authtoken::interface: 'internal'
            nova::keystone::authtoken::memcache_use_advanced_pool: {get_param: MemcacheUseAdvancedPool}
            nova::api::max_limit: {get_param: NovaApiMaxLimit}
            nova::api::enabled: true
            nova::network::neutron::default_floating_pool: {get_param: NovaDefaultFloatingPool}
            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::policy::policies: {get_param: NovaApiPolicies}
            nova::api::allow_resize_to_same_host: {get_param: NovaAllowResizeToSameHost}
            nova_enable_db_purge: {get_param: NovaEnableDBPurge}
            nova::cron::purge_shadow_tables::minute: {get_param: NovaCronPurgeShadowTablesMinute}
            nova::cron::purge_shadow_tables::hour: {get_param: NovaCronPurgeShadowTablesHour}
            nova::cron::purge_shadow_tables::monthday: {get_param: NovaCronPurgeShadowTablesMonthday}
            nova::cron::purge_shadow_tables::month: {get_param: NovaCronPurgeShadowTablesMonth}
            nova::cron::purge_shadow_tables::weekday: {get_param: NovaCronPurgeShadowTablesWeekday}
            nova::cron::purge_shadow_tables::user: {get_param: NovaCronPurgeShadowTablesUser}
            nova::cron::purge_shadow_tables::destination: {get_param: NovaCronPurgeShadowTablesDestination}
            nova::cron::purge_shadow_tables::maxdelay: {get_param: NovaCronPurgeShadowTablesMaxDelay}
            nova::cron::purge_shadow_tables::age: {get_param: NovaCronPurgeShadowTablesAge}
            nova::cron::purge_shadow_tables::verbose: {get_param: NovaCronPurgeShadowTablesVerbose}
            nova::cron::purge_shadow_tables::all_cells: {get_param: NovaCronPurgeShadowTablesAllCells}
            nova_enable_db_archive: {get_param: NovaEnableDBArchive}
            nova::cron::archive_deleted_rows::minute: {get_param: NovaCronArchiveDeleteRowsMinute}
            nova::cron::archive_deleted_rows::hour: {get_param: NovaCronArchiveDeleteRowsHour}
            nova::cron::archive_deleted_rows::monthday: {get_param: NovaCronArchiveDeleteRowsMonthday}
            nova::cron::archive_deleted_rows::month: {get_param: NovaCronArchiveDeleteRowsMonth}
            nova::cron::archive_deleted_rows::weekday: {get_param: NovaCronArchiveDeleteRowsWeekday}
            nova::cron::archive_deleted_rows::max_rows: {get_param: NovaCronArchiveDeleteRowsMaxRows}
            nova::cron::archive_deleted_rows::user: {get_param: NovaCronArchiveDeleteRowsUser}
            nova::cron::archive_deleted_rows::destination: {get_param: NovaCronArchiveDeleteRowsDestination}
            nova::cron::archive_deleted_rows::maxdelay: {get_param: NovaCronArchiveDeleteRowsMaxDelay}
            nova::cron::archive_deleted_rows::until_complete: {get_param: NovaCronArchiveDeleteRowsUntilComplete}
            nova::cron::archive_deleted_rows::purge: {get_param: NovaCronArchiveDeleteRowsPurge}
            nova::cron::archive_deleted_rows::all_cells: {get_param: NovaCronArchiveDeleteAllCells}
            nova::cron::archive_deleted_rows::age: {get_param: NovaCronArchiveDeleteRowsAge}
            nova::cron::archive_deleted_rows::task_log: {get_param: NovaCronArchiveDeleteRowsTaskLog}
            nova::policy::enforce_new_defaults: {get_param: EnforceSecureRbac}
            nova::policy::enforce_scope: {get_param: EnforceSecureRbac}
          - if:
            - nova_workers_set
            - nova::api::osapi_compute_workers: {get_param: NovaWorkers}
              nova::wsgi::apache_api::workers: {get_param: NovaWorkers}
      service_config_settings:
        rabbitmq: {get_attr: [NovaBase, role_data, service_config_settings], rabbitmq}
        mysql:
          map_merge:
            - get_attr: [NovaApiDBClient, role_data, service_config_settings, mysql]
            - get_attr: [NovaDBClient, role_data, service_config_settings, mysql]
        rsyslog:
          tripleo_logging_sources_nova_api:
            - {get_param: NovaApiLoggingSource}
      # 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: &nova_api_db_sync
            - 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/etc/httpd/conf.modules.d"
              dest: "/etc/httpd/conf.modules.d"
              merge: false
              preserve_properties: true
            - source: "/var/lib/kolla/config_files/src/*"
              dest: "/"
              merge: true
              preserve_properties: true
          permissions: &nova_api_permissions
            - path: /var/log/nova
              owner: nova:nova
              recurse: true
        /var/lib/kolla/config_files/nova_api_db_sync.json:
          command: "/usr/bin/bootstrap_host_exec nova_api su nova -s /bin/bash -c '/usr/bin/nova-manage api_db sync'"
          config_files: *nova_api_db_sync
          permissions: *nova_api_permissions
        /var/lib/kolla/config_files/nova_api_map_cell0.json:
          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}'
          config_files: *nova_api_db_sync
          permissions: *nova_api_permissions
        /var/lib/kolla/config_files/nova_api_ensure_default_cell.json:
          command: "/usr/bin/bootstrap_host_exec nova_api /nova_api_ensure_default_cell.sh"
          config_files: *nova_api_db_sync
          permissions: *nova_api_permissions
        /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: *nova_api_permissions
        /var/lib/kolla/config_files/nova_wait_for_api_service.json:
          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'"
          config_files: *nova_api_db_sync
          permissions: *nova_api_permissions

      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:
              list_concat:
                - {get_attr: [ContainersCommon, volumes]}
                - {get_attr: [NovaApiLogging, volumes]}
                - - /var/lib/kolla/config_files/nova_api_db_sync.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
              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:
              list_concat:
                - {get_attr: [ContainersCommon, volumes]}
                - {get_attr: [NovaApiLogging, volumes]}
                - - /var/lib/kolla/config_files/nova_api_map_cell0.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
          nova_api_ensure_default_cell:
            start_order: 2 # Runs before nova-conductor dbsync
            image: *nova_api_image
            net: host
            detach: false
            volumes:
              list_concat:
                - {get_attr: [ContainersCommon, volumes]}
                - {get_attr: [NovaApiLogging, volumes]}
                - - /var/lib/kolla/config_files/nova_api_ensure_default_cell.json:/var/lib/kolla/config_files/config.json:ro
                  - /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
            environment:
              KOLLA_CONFIG_STRATEGY: COPY_ALWAYS
        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:
                    - {get_param: EnableInternalTLS}
                    - - /etc/pki/tls/certs/httpd:/etc/pki/tls/certs/httpd:ro
                      - /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]}
                - {get_attr: [NovaApiLogging, volumes]}
                - - /var/lib/kolla/config_files/nova_wait_for_api_service.json:/var/lib/kolla/config_files/config.json:ro
                  - /var/lib/config-data/puppet-generated/nova:/var/lib/kolla/config_files/src:ro
                  - /var/lib/container-config-scripts/:/container-config-scripts/:z
            environment:
              __OS_DEBUG:
                yaql:
                  expression: str($.data.debug)
                  data:
                    debug: {get_attr: [NovaBase, role_data, config_settings, 'nova::logging::debug']}
              KOLLA_CONFIG_STRATEGY: COPY_ALWAYS
          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:
        list_concat:
          - get_attr: [ApacheServiceBase, role_data, deploy_steps_tasks]
          - - name: validate nova-api container state
              containers.podman.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
          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([]) }}"

{'fraction_non_alphanumeric': 0.08574686431014823, 'fraction_numerical': 0.0033330409613191825, 'mean_word_length': 2.062533576877619, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 68, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7651163', 'n_tokens_mistral': 17046, 'n_tokens_neox': 16441, 'n_words': 3414}