heat_template_version: rocky

description: >
  OpenStack containerized Nova Vncproxy service

parameters:
  ContainerNovaVncProxyImage:
    description: image
    type: string
  ContainerNovaConfigImage:
    description: The container image to use for the nova config_volume
    type: string
  NovaVncproxyLoggingSource:
    type: json
    default:
      tag: openstack.nova.vncproxy
      file: /var/log/containers/nova/nova-vncproxy.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
  EnableInternalTLS:
    type: boolean
    default: false
  UseTLSTransportForVnc:
    type: boolean
    default: true
    description: If set to true and if EnableInternalTLS is enabled, it will
                 enable TLS transaport for libvirt VNC and configure the
                 relevant keys for libvirt.
  InternalTLSVncProxyCAFile:
    default: '/etc/pki/CA/certs/vnc.crt'
    type: string
    description: Specifies the CA cert to use for VNC TLS.
  LibvirtVncCACert:
    type: string
    default: ''
    description: This specifies the CA certificate to use for VNC TLS.
                 This file will be symlinked to the default CA path,
                 which is /etc/pki/libvirt-vnc/ca-cert.pem.
                 This parameter should be used if the default (which comes from
                 the InternalTLSVncProxyCAFile parameter) is not desired. The current
                 default reflects TripleO's default CA, which is FreeIPA.
                 It will only be used if internal TLS is enabled.
  StackUpdateType:
    type: string
    description: >
      Type of update, to differentiate between UPGRADE and UPDATE cases
      when StackAction is UPDATE (both are the same stack action).
    constraints:
    - allowed_values: ['', 'UPGRADE', 'FASTFORWARDUPGRADE']
    default: ''


conditions:

  use_tls_for_vnc:
    and:
    - equals:
      - {get_param: EnableInternalTLS}
      - true
    - equals:
      - {get_param: UseTLSTransportForVnc}
      - true

  libvirt_vnc_specific_ca_unset:
    equals:
      - {get_param: LibvirtVncCACert}
      - ''

  allow_noauth:
    # Allow noauth VNC connections during P->Q upgrade. Remove in Rocky.
    equals: [{get_param: StackUpdateType}, 'UPGRADE']

resources:

  ContainersCommon:
    type: ../containers-common.yaml

  MySQLClient:
    type: ../../deployment/database/mysql-client.yaml

  NovaLogging:
    type: OS::TripleO::Services::Logging::NovaCommon
    properties:
      ContainerNovaImage: {get_param: ContainerNovaVncProxyImage}
      NovaServiceName: 'vncproxy'

  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 Vncproxy service.
    value:
      service_name: nova_vnc_proxy
      firewall_rules:
        '137 nova_vnc_proxy':
          dport:
            - 6080
            - 13080
      config_settings:
        map_merge:
          - {get_attr: [NovaLogging, config_settings]}
          - nova::vncproxy::enabled: true
            nova::vncproxy::common::vncproxy_protocol: {get_param: [EndpointMap, NovaVNCProxyCellPublic, protocol]}
            nova::vncproxy::common::vncproxy_host: {get_param: [EndpointMap, NovaVNCProxyCellPublic, host_nobrackets]}
            nova::vncproxy::common::vncproxy_port: {get_param: [EndpointMap, NovaVNCProxyCellPublic, port]}
            # 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::vncproxy::host:
              str_replace:
                template:
                  "%{hiera('$NETWORK')}"
                params:
                  $NETWORK: {get_param: [ServiceNetMap, NovaApiNetwork]}
          -
            if:
              - use_tls_for_vnc
              -
                nova::vncproxy::allow_vencrypt: true
                nova::vncproxy::allow_noauth: {if: [allow_noauth, true, false]}
                nova::vncproxy::vencrypt_key: /etc/pki/libvirt-vnc/client-key.pem
                nova::vncproxy::vencrypt_cert: /etc/pki/libvirt-vnc/client-cert.pem
                nova::vncproxy::vencrypt_ca: /etc/pki/libvirt-vnc/ca-cert.pem
                nova::ssl_only: true
                nova::cert: /etc/pki/tls/certs/novnc_proxy.crt
                nova::key: /etc/pki/tls/private/novnc_proxy.key
                generate_service_certificates: true
                tripleo::certmonger::ca::libvirt_vnc::origin_ca_pem:
                  if:
                    - libvirt_vnc_specific_ca_unset
                    - get_param: InternalTLSVncProxyCAFile
                    - get_param: LibvirtVncCACert
                tripleo::certmonger::libvirt_vnc_dirs::certificate_dir: '/etc/pki/libvirt-vnc'
                libvirt_vnc_certificates_specs:
                  libvirt-vnc-client-cert:
                    cacertfile:
                      if:
                        - libvirt_vnc_specific_ca_unset
                        - get_param: InternalTLSVncProxyCAFile
                        - null
                    service_certificate: '/etc/pki/libvirt-vnc/client-cert.pem'
                    service_key: '/etc/pki/libvirt-vnc/client-key.pem'
                    notify_service: '%{::nova::params::vncproxy_service_name}'
                    hostname:
                      str_replace:
                        template: "%{hiera('fqdn_NETWORK')}"
                        params:
                          NETWORK: {get_param: [ServiceNetMap, NovaVncProxyNetwork]}
                    principal:
                      str_replace:
                        template: "libvirt-vnc/%{hiera('fqdn_NETWORK')}"
                        params:
                          NETWORK: {get_param: [ServiceNetMap, NovaVncProxyNetwork]}
                novnc_proxy_certificates_specs:
                  service_certificate: '/etc/pki/tls/certs/novnc_proxy.crt'
                  service_key: '/etc/pki/tls/private/novnc_proxy.key'
                  hostname:
                    str_replace:
                      template: "%{hiera('fqdn_NETWORK')}"
                      params:
                        NETWORK: {get_param: [ServiceNetMap, NovaApiNetwork]}
                  principal:
                    str_replace:
                      template: "novnc-proxy/%{hiera('fqdn_NETWORK')}"
                      params:
                        NETWORK: {get_param: [ServiceNetMap, NovaApiNetwork]}
              - {}
      service_config_settings:
        rsyslog:
          tripleo_logging_sources_nova_vnc_proxy:
            - {get_param: NovaVncproxyLoggingSource}
      # BEGIN DOCKER SETTINGS
      puppet_config:
        config_volume: nova
        puppet_tags: nova_config
        step_config:
          list_join:
            - "\n"
            - - include tripleo::profile::base::nova::vncproxy
              - {get_attr: [MySQLClient, role_data, step_config]}
        config_image: {get_param: ContainerNovaConfigImage}
      kolla_config:
        /var/lib/kolla/config_files/nova_vnc_proxy.json:
          command:
            list_join:
            - ' '
            - - /usr/bin/nova-novncproxy --web /usr/share/novnc/
              - get_attr: [NovaLogging, cmd_extra_args]
          config_files:
            - source: "/var/lib/kolla/config_files/src/*"
              dest: "/"
              merge: true
              preserve_properties: true
            - source: "/var/lib/kolla/config_files/src-tls/*"
              dest: "/"
              merge: true
              preserve_properties: true
              optional: true
          permissions:
            - path: /var/log/nova
              owner: nova:nova
              recurse: true
            - path: /etc/pki/tls/private/novnc_proxy.key
              owner: root:nova
      docker_config:
        step_4:
          nova_vnc_proxy:
            image: {get_param: ContainerNovaVncProxyImage}
            net: host
            privileged: false
            restart: always
            healthcheck:
              test: /openstack/healthcheck
            volumes:
              list_concat:
                - {get_attr: [ContainersCommon, volumes]}
                - {get_attr: [NovaLogging, volumes]}
                -
                  - /var/lib/kolla/config_files/nova_vnc_proxy.json:/var/lib/kolla/config_files/config.json:ro
                  - /var/lib/config-data/puppet-generated/nova/:/var/lib/kolla/config_files/src:ro
                -
                  if:
                    - use_tls_for_vnc
                    -
                      - str_replace:
                          template: "CACERT:/etc/pki/libvirt-vnc/ca-cert.pem:ro"
                          params:
                            CACERT:
                              if:
                                - libvirt_vnc_specific_ca_unset
                                - get_param: InternalTLSVncProxyCAFile
                                - get_param: LibvirtVncCACert
                      - /etc/pki/libvirt-vnc/client-cert.pem:/etc/pki/libvirt-vnc/client-cert.pem:ro
                      - /etc/pki/libvirt-vnc/client-key.pem:/etc/pki/libvirt-vnc/client-key.pem:ro
                      - /etc/pki/tls/certs/novnc_proxy.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/novnc_proxy.crt:ro
                      - /etc/pki/tls/private/novnc_proxy.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/novnc_proxy.key:ro
                    - null
            environment:
              KOLLA_CONFIG_STRATEGY: COPY_ALWAYS
      metadata_settings:
        if:
          - use_tls_for_vnc
          -
            - service: libvirt-vnc
              network: {get_param: [ServiceNetMap, NovaVncProxyNetwork]}
              type: node
            - service: novnc-proxy
              network: {get_param: [ServiceNetMap, NovaApiNetwork]}
              type: node
          - null
      deploy_steps_tasks:
        - name: validate nova-vnc-proxy container state
          when:
            - container_cli == 'podman'
            - not container_healthcheck_disabled
            - step|int == 5
          tags:
            - opendev-validation
            - opendev-validation-nova
          block:
            - name: Get nova-vnc-proxy healthcheck status
              register: nova_vnc_proxy_healthcheck_state
              systemd:
                name: tripleo_nova_vnc_proxy_healthcheck
              retries: 10
              delay: 30
              until: nova_vnc_proxy_healthcheck_state.status.ExecMainPID != '0' and
                nova_vnc_proxy_healthcheck_state.status.ActiveState in ['inactive', 'failed']
              ignore_errors: yes
            - name: Fail if nova-vnc-proxy healtcheck report failed status
              fail:
                msg: nova-vnc-proxy isn't working (healthcheck failed)
              when: nova_vnc_proxy_healthcheck_state.status.ExecMainStatus != '0'
      host_prep_tasks: {get_attr: [NovaLogging, host_prep_tasks]}
      fast_forward_upgrade_tasks:
        - when:
            - step|int == 0
            - release == 'ocata'
          block:
            - name: Check if nova vncproxy is deployed
              command: systemctl is-enabled --quiet openstack-nova-novncproxy
              ignore_errors: True
              register: nova_vncproxy_enabled_result
            - name: Set fact nova_vncproxy_enabled
              set_fact:
                nova_vncproxy_enabled: "{{ nova_vncproxy_enabled_result.rc == 0 }}"
        - name: Stop and disable nova-novncproxy service
          service: name=openstack-nova-novncproxy state=stopped
          when:
            - step|int == 1
            - release == 'ocata'
            - nova_vncproxy_enabled|bool
      external_upgrade_tasks:
        - when:
            - step|int == 1
          tags:
            - never
            - system_upgrade_transfer_data
            - system_upgrade_stop_services
          block:
            - name: Stop nova vnc proxy container
              import_role:
                name: tripleo-container-stop
              vars:
                tripleo_containers_to_stop:
                  - nova_vnc_proxy
                tripleo_delegate_to: "{{ groups['nova_vnc_proxy'] | default([]) }}"
