all:
  children:
    tempest:
      hosts:
        controller: null
    zuul_unreachable:
      hosts: {}
  hosts:
    controller:
      ansible_connection: ssh
      ansible_host: 199.19.213.10
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      configure_swap_size: 8192
      devstack_local_conf:
        post-config:
          $NEUTRON_CONF:
            DEFAULT:
              global_physnet_mtu: '{{ external_bridge_mtu }}'
          /etc/magnum/magnum.conf:
            cluster_template:
              kubernetes_allowed_network_drivers: calico,cilium
              kubernetes_default_network_driver: calico
            nova_client:
              api_version: 2.15
          /etc/manila/manila.conf:
            generic:
              connect_share_server_to_tenant_network: true
              driver_handles_share_servers: true
      devstack_localrc:
        ADMIN_PASSWORD: secretadmin
        DATABASE_PASSWORD: secretdatabase
        DEBUG_LIBVIRT_COREDUMPS: true
        DISABLE_AMP_IMAGE_BUILD: true
        ENABLE_SYSCTL_MEM_TUNING: true
        ENABLE_SYSCTL_NET_TUNING: true
        ENABLE_ZSWAP: true
        ERROR_ON_CLONE: true
        FIXED_RANGE: 10.1.0.0/20
        FLOATING_RANGE: 172.24.5.0/24
        GIT_BASE: https://github.com
        HOST_IP: '{{ hostvars[''controller''][''nodepool''][''private_ipv4''] }}'
        IPV4_ADDRS_SAFE_TO_USE: 10.1.0.0/20
        LIBVIRT_TYPE: '{{ devstack_libvirt_type | default("qemu") }}'
        LOGFILE: /opt/stack/logs/devstacklog.txt
        LOG_COLOR: false
        MAGNUM_GUEST_IMAGE_URL: '{{ image_url }}'
        MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: snapshot_support=True create_share_from_snapshot_support=True
        MANILA_ENABLED_BACKENDS: generic
        MANILA_USE_SERVICE_INSTANCE_PASSWORD: true
        NETWORK_GATEWAY: 10.1.0.1
        NOVA_LIBVIRT_TB_CACHE_SIZE: 128
        NOVA_VNC_ENABLED: true
        OCTAVIA_NODE: api
        OVN_DBS_LOG_LEVEL: dbg
        PUBLIC_BRIDGE_MTU: '{{ external_bridge_mtu }}'
        PUBLIC_NETWORK_GATEWAY: 172.24.5.1
        RABBIT_PASSWORD: secretrabbit
        SERVICE_HOST: '{{ hostvars[''controller''][''nodepool''][''private_ipv4'']
          }}'
        SERVICE_PASSWORD: secretservice
        SWIFT_HASH: 1234123412341234
        SWIFT_REPLICAS: 1
        SWIFT_START_ALL_SERVICES: false
        VERBOSE: true
        VERBOSE_NO_TIMESTAMP: true
      devstack_plugins:
        barbican: https://github.com/openstack/barbican
        magnum: https://review.opendev.org/openstack/magnum
        magnum-cluster-api: https://github.com/vexxhost/magnum-cluster-api
        manila: https://github.com/openstack/manila
        octavia: https://github.com/openstack/octavia
        ovn-octavia-provider: https://github.com/openstack/ovn-octavia-provider
      devstack_services:
        base: false
        c-api: true
        c-bak: true
        c-sch: true
        c-vol: true
        dstat: false
        etcd3: true
        file_tracker: true
        g-api: true
        horizon: false
        key: true
        memory_tracker: true
        mysql: true
        n-api: true
        n-api-meta: true
        n-cond: true
        n-cpu: true
        n-novnc: true
        n-sch: true
        o-api: true
        o-da: true
        o-hk: true
        octavia: true
        openstack-cli-server: true
        ovn-controller: true
        ovn-northd: true
        ovs-vswitchd: true
        ovsdb-server: true
        placement-api: true
        q-ovn-agent: true
        q-svc: true
        rabbit: true
        s-account: false
        s-container: false
        s-object: false
        s-proxy: false
        tempest: false
        tls-proxy: true
      extensions_to_txt:
        auto: true
        conf: true
        localrc: true
        log: true
        stackenv: true
      image_url: https://github.com/vexxhost/capo-image-elements/releases/latest/download/ubuntu-22.04-{{
        kube_tag }}.qcow2
      kube_tag: v1.35.3
      network_driver: cilium
      nodepool:
        az: nova
        cloud: public
        external_id: 12cc6f6f-cda8-4188-baea-e8bd56b3818b
        host_id: dc47ae3b6bd7105f226a81ddfc9102f715bac5cc73984e91b5981caa
        interface_ip: 199.19.213.10
        label: ubuntu-noble-16
        node_properties: {}
        private_ipv4: 199.19.213.10
        private_ipv6: null
        provider: yul1
        public_ipv4: 199.19.213.10
        public_ipv6: 2604:e100:1:0:f816:3eff:fef8:1421
        region: ca-ymq-1
        slot: null
      zuul_copy_output:
        /etc/ceph: logs
        /etc/glusterfs/glusterd.vol: logs
        /etc/libvirt: logs
        /etc/lvm: logs
        /etc/resolv.conf: logs
        /etc/sudoers: logs
        /etc/sudoers.d: logs
        /var/log/ceph: logs
        /var/log/glusterfs: logs
        /var/log/libvirt: logs
        /var/log/mysql: logs
        /var/log/openvswitch: logs
        /var/log/postgresql: logs
        /var/log/rabbitmq: logs
        /var/log/unbound.log: logs
        '{{ devstack_conf_dir }}/.localrc.auto': logs
        '{{ devstack_conf_dir }}/.stackenv': logs
        '{{ devstack_conf_dir }}/local.conf': logs
        '{{ devstack_conf_dir }}/localrc': logs
        '{{ devstack_full_log}}': logs
        '{{ devstack_log_dir }}/atop': logs
        '{{ devstack_log_dir }}/devstacklog.txt': logs
        '{{ devstack_log_dir }}/devstacklog.txt.summary': logs
        '{{ devstack_log_dir }}/dstat-csv.log': logs
        '{{ devstack_log_dir }}/qemu.coredump': logs
        '{{ devstack_log_dir }}/tcpdump.pcap': logs
        '{{ devstack_log_dir }}/worlddump-latest.txt': logs
        '{{ stage_dir }}/apache': logs
        '{{ stage_dir }}/apache_config': logs
        '{{ stage_dir }}/audit.log': logs
        '{{ stage_dir }}/core': logs
        '{{ stage_dir }}/deprecations.log': logs
        '{{ stage_dir }}/df.txt': logs
        '{{ stage_dir }}/dpkg-l.txt': logs
        '{{ stage_dir }}/etc': logs
        '{{ stage_dir }}/iptables.txt': logs
        '{{ stage_dir }}/listen53.txt': logs
        '{{ stage_dir }}/mount.txt': logs
        '{{ stage_dir }}/performance.json': logs
        '{{ stage_dir }}/pip2-freeze.txt': logs
        '{{ stage_dir }}/pip3-freeze.txt': logs
        '{{ stage_dir }}/rpm-qa.txt': logs
        '{{ stage_dir }}/services.txt': logs
        '{{ stage_dir }}/verify_tempest_conf.log': logs
      zuul_node:
        az: nova
        cloud: public
        external_id: 12cc6f6f-cda8-4188-baea-e8bd56b3818b
        host_id: dc47ae3b6bd7105f226a81ddfc9102f715bac5cc73984e91b5981caa
        interface_ip: 199.19.213.10
        label: ubuntu-noble-16
        node_properties: {}
        private_ipv4: 199.19.213.10
        private_ipv6: null
        provider: yul1
        public_ipv4: 199.19.213.10
        public_ipv6: 2604:e100:1:0:f816:3eff:fef8:1421
        region: ca-ymq-1
        slot: null
        uuid: null
  vars:
    configure_swap_size: 8192
    devstack_local_conf:
      post-config:
        $NEUTRON_CONF:
          DEFAULT:
            global_physnet_mtu: '{{ external_bridge_mtu }}'
        /etc/magnum/magnum.conf:
          cluster_template:
            kubernetes_allowed_network_drivers: calico,cilium
            kubernetes_default_network_driver: calico
          nova_client:
            api_version: 2.15
        /etc/manila/manila.conf:
          generic:
            connect_share_server_to_tenant_network: true
            driver_handles_share_servers: true
    devstack_localrc:
      ADMIN_PASSWORD: secretadmin
      DATABASE_PASSWORD: secretdatabase
      DEBUG_LIBVIRT_COREDUMPS: true
      DISABLE_AMP_IMAGE_BUILD: true
      ENABLE_SYSCTL_MEM_TUNING: true
      ENABLE_SYSCTL_NET_TUNING: true
      ENABLE_ZSWAP: true
      ERROR_ON_CLONE: true
      FIXED_RANGE: 10.1.0.0/20
      FLOATING_RANGE: 172.24.5.0/24
      GIT_BASE: https://github.com
      HOST_IP: '{{ hostvars[''controller''][''nodepool''][''private_ipv4''] }}'
      IPV4_ADDRS_SAFE_TO_USE: 10.1.0.0/20
      LIBVIRT_TYPE: '{{ devstack_libvirt_type | default("qemu") }}'
      LOGFILE: /opt/stack/logs/devstacklog.txt
      LOG_COLOR: false
      MAGNUM_GUEST_IMAGE_URL: '{{ image_url }}'
      MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: snapshot_support=True create_share_from_snapshot_support=True
      MANILA_ENABLED_BACKENDS: generic
      MANILA_USE_SERVICE_INSTANCE_PASSWORD: true
      NETWORK_GATEWAY: 10.1.0.1
      NOVA_LIBVIRT_TB_CACHE_SIZE: 128
      NOVA_VNC_ENABLED: true
      OCTAVIA_NODE: api
      OVN_DBS_LOG_LEVEL: dbg
      PUBLIC_BRIDGE_MTU: '{{ external_bridge_mtu }}'
      PUBLIC_NETWORK_GATEWAY: 172.24.5.1
      RABBIT_PASSWORD: secretrabbit
      SERVICE_HOST: '{{ hostvars[''controller''][''nodepool''][''private_ipv4''] }}'
      SERVICE_PASSWORD: secretservice
      SWIFT_HASH: 1234123412341234
      SWIFT_REPLICAS: 1
      SWIFT_START_ALL_SERVICES: false
      VERBOSE: true
      VERBOSE_NO_TIMESTAMP: true
    devstack_plugins:
      barbican: https://github.com/openstack/barbican
      magnum: https://review.opendev.org/openstack/magnum
      magnum-cluster-api: https://github.com/vexxhost/magnum-cluster-api
      manila: https://github.com/openstack/manila
      octavia: https://github.com/openstack/octavia
      ovn-octavia-provider: https://github.com/openstack/ovn-octavia-provider
    devstack_services:
      base: false
      c-api: true
      c-bak: true
      c-sch: true
      c-vol: true
      dstat: false
      etcd3: true
      file_tracker: true
      g-api: true
      horizon: false
      key: true
      memory_tracker: true
      mysql: true
      n-api: true
      n-api-meta: true
      n-cond: true
      n-cpu: true
      n-novnc: true
      n-sch: true
      o-api: true
      o-da: true
      o-hk: true
      octavia: true
      openstack-cli-server: true
      ovn-controller: true
      ovn-northd: true
      ovs-vswitchd: true
      ovsdb-server: true
      placement-api: true
      q-ovn-agent: true
      q-svc: true
      rabbit: true
      s-account: false
      s-container: false
      s-object: false
      s-proxy: false
      tempest: false
      tls-proxy: true
    extensions_to_txt:
      auto: true
      conf: true
      localrc: true
      log: true
      stackenv: true
    image_url: https://github.com/vexxhost/capo-image-elements/releases/latest/download/ubuntu-22.04-{{
      kube_tag }}.qcow2
    kube_tag: v1.35.3
    network_driver: cilium
    zuul:
      _inheritance_path:
      - '<Job base explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: vexxhost/zuul-config/zuul.d/jobs.yaml@main#1>'
      - '<Job openstack-multinode-fips explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: vexxhost/zuul-config/zuul.d/jobs.yaml@main#17>'
      - '<Job devstack-base explicit: None implied: {MatchAny:{ImpliedBranchMatcher:master}}
        source: openstack/devstack/.zuul.yaml@master#368>'
      - '<Job devstack-minimal explicit: None implied: {MatchAny:{ImpliedBranchMatcher:master}}
        source: openstack/devstack/.zuul.yaml@master#502>'
      - '<Job devstack explicit: None implied: {MatchAny:{ImpliedBranchMatcher:master}}
        source: openstack/devstack/.zuul.yaml@master#545>'
      - '<Job magnum-cluster-api-devstack explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: vexxhost/magnum-cluster-api/zuul.d/jobs.yaml@main#1>'
      - '<Job magnum-cluster-api-hydrophone explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: vexxhost/magnum-cluster-api/zuul.d/jobs.yaml@main#60>'
      - '<Job magnum-cluster-api-hydrophone-v1.35.3 explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: vexxhost/magnum-cluster-api/zuul.d/jobs.yaml@main#108>'
      - '<Job magnum-cluster-api-hydrophone-v1.35.3-cilium explicit: None implied:
        {MatchAny:{ImpliedBranchMatcher:main}} source: vexxhost/magnum-cluster-api/zuul.d/jobs.yaml@main#120>'
      - '<Job magnum-cluster-api-hydrophone-v1.35.3-cilium explicit: None implied:
        None source: vexxhost/magnum-cluster-api/zuul.d/project.yaml@main#1>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: 444150d40f2341fcb15d21e5a2468974
      build_refs:
      - branch: main
        change: '956'
        change_message: "fix: preserve immutable OpenStackCluster fields and version
          cluster class names\n\n## Problem\n\nCAPI's topology controller applies
          JSON patches by replacing entire objects\n(e.g. `apiServerLoadBalancer`),
          not merging individual fields. Previously,\n`resources.py` only included
          optional fields like `provider`, `flavor`, and\n`availabilityZone` when
          their corresponding labels were set. On subsequent\nupdates where those
          labels are absent, CAPI replaces the whole object with one\nmissing those
          fields \u2014 triggering immutable-field validation errors on the\nexisting
          `OpenStackCluster`.\n\nSeparately, dev/PR builds used `importlib.metadata.version()`
          for the cluster\nclass name (`magnum-v0.36.2`), so non-release builds would
          collide with the\nrelease version and hit `OpenStackClusterTemplate` immutable
          errors.\n\n## Changes\n\n### New: `src/immutable_fields.rs`\n\nData-driven
          field mapping system that reads the **existing** `OpenStackCluster`\nresource
          from the K8s API before rebuilding topology variables:\n\n- `FieldMapping`
          \u2014 maps a resource JSON pointer (`/spec/apiServerLoadBalancer/provider`)\n
          \ to a variable JSON pointer (`/apiServerLoadBalancer/provider`) with a
          label fallback\n- `ResourceFieldMappings<T>` \u2014 generic over any namespaced
          K8s resource; handles\n  API list-by-label, serialization, and folding field
          mappings over the variables\n- `OPENSTACK_CLUSTER_FIELDS` \u2014 const mapping
          for `provider`, `flavor`, `availabilityZone`\n- Resolution priority: existing
          resource value \u2192 label fallback \u2192 omit\n- Uses `jsonptr` crate
          for RFC 6901 pointer resolve/assign\n- 15 unit tests across `parse_pointer`,
          `field_mapping`, and `openstack_cluster` modules\n\n### New: `src/cluster_api/openstackclusters.rs`\n\nkopium-generated
          typed `OpenStackCluster` CRD (CAPO v0.11.6) enabling\n`Api<OpenStackCluster>`
          for type-safe K8s API calls in the field resolver.\n\n### Changed: `src/driver.rs`\n\n-
          New `resolve_immutable_fields` pymethod: deserializes Python dict \u2192
          `serde_json::Value`,\n  calls `OPENSTACK_CLUSTER_FIELDS.resolve()` via tokio
          runtime, returns result to Python\n- `create_exception!(ImmutableFieldError)`
          + `From<immutable_fields::Error> for PyErr` \u2014\n  PyO3 error boundary
          lives here, keeping `immutable_fields.rs` free of pyo3 deps\n- Removed `cluster_class_name`
          field from `Driver` struct; `apply_cluster_class` uses\n  the module-level
          `CLUSTER_CLASS_NAME` directly\n\n### Changed: `src/lib.rs`\n\n- `CLUSTER_CLASS_NAME`
          is now `LazyLock<String>` = `magnum-{VERGEN_GIT_DESCRIBE}` \u2014\n  each
          build gets a unique name derived from `git describe`\n- Exposed as `magnum_cluster_api.CLUSTER_CLASS_NAME`
          to Python\n\n### Changed: `build.rs`\n\nAdded `vergen-gix` emission so `VERGEN_GIT_DESCRIBE`
          is available at compile time.\n\n### Changed: `magnum_cluster_api/resources.py`\n\n-
          Removed `CLUSTER_CLASS_VERSION` / `CLUSTER_CLASS_NAME` constants and `importlib.metadata`\n-
          `Cluster.__init__` now takes a **required** `rust_driver` parameter\n- Removed
          `_resolve_immutable_fields` wrapper method\n- `get_object()` calls `self.rust_driver.resolve_immutable_fields()`
          directly instead of\n  conditionally building `api_server_load_balancer`
          dict from labels\n- Topology class references `magnum_cluster_api.CLUSTER_CLASS_NAME`
          (from Rust)\n\n### Changed: `magnum_cluster_api/driver.py`\n\n- `BaseDriver.__init__`
          passes only `namespace` to `Driver()` (no more `cluster_class_name`)\n-
          All four `resources.Cluster()` call sites (create, status check, update,
          delete) now\n  pass `rust_driver=self.rust_driver`\n\n### Changed: `release-please-config.json`
          / `pyproject.toml`\n\n- Switched to `release-type: rust` so `Cargo.toml`
          is the version source of truth\n- `pyproject.toml` version is now `dynamic
          = [\"version\"]` (maturin reads from Cargo.toml)\n\n### Changed: tests\n\n-
          `conftest.py`: `mock_rust_driver` fixture patches `Driver` with a passthrough\n
          \ `resolve_immutable_fields` lambda; removed `cluster_topology_variable`
          fixture\n  (no longer has consumers)\n- `test_resources.py`: removed `test_octavia_label_sets_provider`
          and\n  `test_no_octavia_label_omits_provider` (label\u2192variable logic
          is now Rust-only,\n  tested by the 15 Rust unit tests)\n- `test_driver.py`:
          added `rust_driver=ubuntu_driver.rust_driver` to\n  `resources.Cluster()`
          in assertion\n- `functional/fixtures.py`: `ClusterFixture` creates `Driver`
          once, passes it as\n  `rust_driver` to `Cluster` and reuses it for `apply_cluster_class()`\n"
        change_url: https://github.com/vexxhost/magnum-cluster-api/pull/956
        commit_id: 117eb7573d266bd4e42c46b8582806c76c0b460a
        patchset: 117eb7573d266bd4e42c46b8582806c76c0b460a
        project:
          canonical_hostname: github.com
          canonical_name: github.com/vexxhost/magnum-cluster-api
          name: vexxhost/magnum-cluster-api
          short_name: magnum-cluster-api
          src_dir: src/github.com/vexxhost/magnum-cluster-api
        src_dir: src/github.com/vexxhost/magnum-cluster-api
        topic: null
      buildset: f8922a06725a4095b69ec3c67cc724af
      buildset_refs:
      - branch: main
        change: '956'
        change_message: "fix: preserve immutable OpenStackCluster fields and version
          cluster class names\n\n## Problem\n\nCAPI's topology controller applies
          JSON patches by replacing entire objects\n(e.g. `apiServerLoadBalancer`),
          not merging individual fields. Previously,\n`resources.py` only included
          optional fields like `provider`, `flavor`, and\n`availabilityZone` when
          their corresponding labels were set. On subsequent\nupdates where those
          labels are absent, CAPI replaces the whole object with one\nmissing those
          fields \u2014 triggering immutable-field validation errors on the\nexisting
          `OpenStackCluster`.\n\nSeparately, dev/PR builds used `importlib.metadata.version()`
          for the cluster\nclass name (`magnum-v0.36.2`), so non-release builds would
          collide with the\nrelease version and hit `OpenStackClusterTemplate` immutable
          errors.\n\n## Changes\n\n### New: `src/immutable_fields.rs`\n\nData-driven
          field mapping system that reads the **existing** `OpenStackCluster`\nresource
          from the K8s API before rebuilding topology variables:\n\n- `FieldMapping`
          \u2014 maps a resource JSON pointer (`/spec/apiServerLoadBalancer/provider`)\n
          \ to a variable JSON pointer (`/apiServerLoadBalancer/provider`) with a
          label fallback\n- `ResourceFieldMappings<T>` \u2014 generic over any namespaced
          K8s resource; handles\n  API list-by-label, serialization, and folding field
          mappings over the variables\n- `OPENSTACK_CLUSTER_FIELDS` \u2014 const mapping
          for `provider`, `flavor`, `availabilityZone`\n- Resolution priority: existing
          resource value \u2192 label fallback \u2192 omit\n- Uses `jsonptr` crate
          for RFC 6901 pointer resolve/assign\n- 15 unit tests across `parse_pointer`,
          `field_mapping`, and `openstack_cluster` modules\n\n### New: `src/cluster_api/openstackclusters.rs`\n\nkopium-generated
          typed `OpenStackCluster` CRD (CAPO v0.11.6) enabling\n`Api<OpenStackCluster>`
          for type-safe K8s API calls in the field resolver.\n\n### Changed: `src/driver.rs`\n\n-
          New `resolve_immutable_fields` pymethod: deserializes Python dict \u2192
          `serde_json::Value`,\n  calls `OPENSTACK_CLUSTER_FIELDS.resolve()` via tokio
          runtime, returns result to Python\n- `create_exception!(ImmutableFieldError)`
          + `From<immutable_fields::Error> for PyErr` \u2014\n  PyO3 error boundary
          lives here, keeping `immutable_fields.rs` free of pyo3 deps\n- Removed `cluster_class_name`
          field from `Driver` struct; `apply_cluster_class` uses\n  the module-level
          `CLUSTER_CLASS_NAME` directly\n\n### Changed: `src/lib.rs`\n\n- `CLUSTER_CLASS_NAME`
          is now `LazyLock<String>` = `magnum-{VERGEN_GIT_DESCRIBE}` \u2014\n  each
          build gets a unique name derived from `git describe`\n- Exposed as `magnum_cluster_api.CLUSTER_CLASS_NAME`
          to Python\n\n### Changed: `build.rs`\n\nAdded `vergen-gix` emission so `VERGEN_GIT_DESCRIBE`
          is available at compile time.\n\n### Changed: `magnum_cluster_api/resources.py`\n\n-
          Removed `CLUSTER_CLASS_VERSION` / `CLUSTER_CLASS_NAME` constants and `importlib.metadata`\n-
          `Cluster.__init__` now takes a **required** `rust_driver` parameter\n- Removed
          `_resolve_immutable_fields` wrapper method\n- `get_object()` calls `self.rust_driver.resolve_immutable_fields()`
          directly instead of\n  conditionally building `api_server_load_balancer`
          dict from labels\n- Topology class references `magnum_cluster_api.CLUSTER_CLASS_NAME`
          (from Rust)\n\n### Changed: `magnum_cluster_api/driver.py`\n\n- `BaseDriver.__init__`
          passes only `namespace` to `Driver()` (no more `cluster_class_name`)\n-
          All four `resources.Cluster()` call sites (create, status check, update,
          delete) now\n  pass `rust_driver=self.rust_driver`\n\n### Changed: `release-please-config.json`
          / `pyproject.toml`\n\n- Switched to `release-type: rust` so `Cargo.toml`
          is the version source of truth\n- `pyproject.toml` version is now `dynamic
          = [\"version\"]` (maturin reads from Cargo.toml)\n\n### Changed: tests\n\n-
          `conftest.py`: `mock_rust_driver` fixture patches `Driver` with a passthrough\n
          \ `resolve_immutable_fields` lambda; removed `cluster_topology_variable`
          fixture\n  (no longer has consumers)\n- `test_resources.py`: removed `test_octavia_label_sets_provider`
          and\n  `test_no_octavia_label_omits_provider` (label\u2192variable logic
          is now Rust-only,\n  tested by the 15 Rust unit tests)\n- `test_driver.py`:
          added `rust_driver=ubuntu_driver.rust_driver` to\n  `resources.Cluster()`
          in assertion\n- `functional/fixtures.py`: `ClusterFixture` creates `Driver`
          once, passes it as\n  `rust_driver` to `Cluster` and reuses it for `apply_cluster_class()`\n"
        change_url: https://github.com/vexxhost/magnum-cluster-api/pull/956
        commit_id: 117eb7573d266bd4e42c46b8582806c76c0b460a
        patchset: 117eb7573d266bd4e42c46b8582806c76c0b460a
        project:
          canonical_hostname: github.com
          canonical_name: github.com/vexxhost/magnum-cluster-api
          name: vexxhost/magnum-cluster-api
          short_name: magnum-cluster-api
          src_dir: src/github.com/vexxhost/magnum-cluster-api
        src_dir: src/github.com/vexxhost/magnum-cluster-api
        topic: null
      change: '956'
      change_message: "fix: preserve immutable OpenStackCluster fields and version
        cluster class names\n\n## Problem\n\nCAPI's topology controller applies JSON
        patches by replacing entire objects\n(e.g. `apiServerLoadBalancer`), not merging
        individual fields. Previously,\n`resources.py` only included optional fields
        like `provider`, `flavor`, and\n`availabilityZone` when their corresponding
        labels were set. On subsequent\nupdates where those labels are absent, CAPI
        replaces the whole object with one\nmissing those fields \u2014 triggering
        immutable-field validation errors on the\nexisting `OpenStackCluster`.\n\nSeparately,
        dev/PR builds used `importlib.metadata.version()` for the cluster\nclass name
        (`magnum-v0.36.2`), so non-release builds would collide with the\nrelease
        version and hit `OpenStackClusterTemplate` immutable errors.\n\n## Changes\n\n###
        New: `src/immutable_fields.rs`\n\nData-driven field mapping system that reads
        the **existing** `OpenStackCluster`\nresource from the K8s API before rebuilding
        topology variables:\n\n- `FieldMapping` \u2014 maps a resource JSON pointer
        (`/spec/apiServerLoadBalancer/provider`)\n  to a variable JSON pointer (`/apiServerLoadBalancer/provider`)
        with a label fallback\n- `ResourceFieldMappings<T>` \u2014 generic over any
        namespaced K8s resource; handles\n  API list-by-label, serialization, and
        folding field mappings over the variables\n- `OPENSTACK_CLUSTER_FIELDS` \u2014
        const mapping for `provider`, `flavor`, `availabilityZone`\n- Resolution priority:
        existing resource value \u2192 label fallback \u2192 omit\n- Uses `jsonptr`
        crate for RFC 6901 pointer resolve/assign\n- 15 unit tests across `parse_pointer`,
        `field_mapping`, and `openstack_cluster` modules\n\n### New: `src/cluster_api/openstackclusters.rs`\n\nkopium-generated
        typed `OpenStackCluster` CRD (CAPO v0.11.6) enabling\n`Api<OpenStackCluster>`
        for type-safe K8s API calls in the field resolver.\n\n### Changed: `src/driver.rs`\n\n-
        New `resolve_immutable_fields` pymethod: deserializes Python dict \u2192 `serde_json::Value`,\n
        \ calls `OPENSTACK_CLUSTER_FIELDS.resolve()` via tokio runtime, returns result
        to Python\n- `create_exception!(ImmutableFieldError)` + `From<immutable_fields::Error>
        for PyErr` \u2014\n  PyO3 error boundary lives here, keeping `immutable_fields.rs`
        free of pyo3 deps\n- Removed `cluster_class_name` field from `Driver` struct;
        `apply_cluster_class` uses\n  the module-level `CLUSTER_CLASS_NAME` directly\n\n###
        Changed: `src/lib.rs`\n\n- `CLUSTER_CLASS_NAME` is now `LazyLock<String>`
        = `magnum-{VERGEN_GIT_DESCRIBE}` \u2014\n  each build gets a unique name derived
        from `git describe`\n- Exposed as `magnum_cluster_api.CLUSTER_CLASS_NAME`
        to Python\n\n### Changed: `build.rs`\n\nAdded `vergen-gix` emission so `VERGEN_GIT_DESCRIBE`
        is available at compile time.\n\n### Changed: `magnum_cluster_api/resources.py`\n\n-
        Removed `CLUSTER_CLASS_VERSION` / `CLUSTER_CLASS_NAME` constants and `importlib.metadata`\n-
        `Cluster.__init__` now takes a **required** `rust_driver` parameter\n- Removed
        `_resolve_immutable_fields` wrapper method\n- `get_object()` calls `self.rust_driver.resolve_immutable_fields()`
        directly instead of\n  conditionally building `api_server_load_balancer` dict
        from labels\n- Topology class references `magnum_cluster_api.CLUSTER_CLASS_NAME`
        (from Rust)\n\n### Changed: `magnum_cluster_api/driver.py`\n\n- `BaseDriver.__init__`
        passes only `namespace` to `Driver()` (no more `cluster_class_name`)\n- All
        four `resources.Cluster()` call sites (create, status check, update, delete)
        now\n  pass `rust_driver=self.rust_driver`\n\n### Changed: `release-please-config.json`
        / `pyproject.toml`\n\n- Switched to `release-type: rust` so `Cargo.toml` is
        the version source of truth\n- `pyproject.toml` version is now `dynamic =
        [\"version\"]` (maturin reads from Cargo.toml)\n\n### Changed: tests\n\n-
        `conftest.py`: `mock_rust_driver` fixture patches `Driver` with a passthrough\n
        \ `resolve_immutable_fields` lambda; removed `cluster_topology_variable` fixture\n
        \ (no longer has consumers)\n- `test_resources.py`: removed `test_octavia_label_sets_provider`
        and\n  `test_no_octavia_label_omits_provider` (label\u2192variable logic is
        now Rust-only,\n  tested by the 15 Rust unit tests)\n- `test_driver.py`: added
        `rust_driver=ubuntu_driver.rust_driver` to\n  `resources.Cluster()` in assertion\n-
        `functional/fixtures.py`: `ClusterFixture` creates `Driver` once, passes it
        as\n  `rust_driver` to `Cluster` and reuses it for `apply_cluster_class()`\n"
      change_url: https://github.com/vexxhost/magnum-cluster-api/pull/956
      child_jobs: []
      commit_id: 117eb7573d266bd4e42c46b8582806c76c0b460a
      event_id: 8ec8bf30-352c-11f1-9f66-9e866c340726
      executor:
        hostname: 0a8996d2b663
        inventory_file: /var/lib/zuul/builds/444150d40f2341fcb15d21e5a2468974/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/444150d40f2341fcb15d21e5a2468974/work/logs
        result_data_file: /var/lib/zuul/builds/444150d40f2341fcb15d21e5a2468974/work/results.json
        src_root: /var/lib/zuul/builds/444150d40f2341fcb15d21e5a2468974/work/src
        work_root: /var/lib/zuul/builds/444150d40f2341fcb15d21e5a2468974/work
      include_vars: []
      items:
      - branch: main
        change: '956'
        change_message: "fix: preserve immutable OpenStackCluster fields and version
          cluster class names\n\n## Problem\n\nCAPI's topology controller applies
          JSON patches by replacing entire objects\n(e.g. `apiServerLoadBalancer`),
          not merging individual fields. Previously,\n`resources.py` only included
          optional fields like `provider`, `flavor`, and\n`availabilityZone` when
          their corresponding labels were set. On subsequent\nupdates where those
          labels are absent, CAPI replaces the whole object with one\nmissing those
          fields \u2014 triggering immutable-field validation errors on the\nexisting
          `OpenStackCluster`.\n\nSeparately, dev/PR builds used `importlib.metadata.version()`
          for the cluster\nclass name (`magnum-v0.36.2`), so non-release builds would
          collide with the\nrelease version and hit `OpenStackClusterTemplate` immutable
          errors.\n\n## Changes\n\n### New: `src/immutable_fields.rs`\n\nData-driven
          field mapping system that reads the **existing** `OpenStackCluster`\nresource
          from the K8s API before rebuilding topology variables:\n\n- `FieldMapping`
          \u2014 maps a resource JSON pointer (`/spec/apiServerLoadBalancer/provider`)\n
          \ to a variable JSON pointer (`/apiServerLoadBalancer/provider`) with a
          label fallback\n- `ResourceFieldMappings<T>` \u2014 generic over any namespaced
          K8s resource; handles\n  API list-by-label, serialization, and folding field
          mappings over the variables\n- `OPENSTACK_CLUSTER_FIELDS` \u2014 const mapping
          for `provider`, `flavor`, `availabilityZone`\n- Resolution priority: existing
          resource value \u2192 label fallback \u2192 omit\n- Uses `jsonptr` crate
          for RFC 6901 pointer resolve/assign\n- 15 unit tests across `parse_pointer`,
          `field_mapping`, and `openstack_cluster` modules\n\n### New: `src/cluster_api/openstackclusters.rs`\n\nkopium-generated
          typed `OpenStackCluster` CRD (CAPO v0.11.6) enabling\n`Api<OpenStackCluster>`
          for type-safe K8s API calls in the field resolver.\n\n### Changed: `src/driver.rs`\n\n-
          New `resolve_immutable_fields` pymethod: deserializes Python dict \u2192
          `serde_json::Value`,\n  calls `OPENSTACK_CLUSTER_FIELDS.resolve()` via tokio
          runtime, returns result to Python\n- `create_exception!(ImmutableFieldError)`
          + `From<immutable_fields::Error> for PyErr` \u2014\n  PyO3 error boundary
          lives here, keeping `immutable_fields.rs` free of pyo3 deps\n- Removed `cluster_class_name`
          field from `Driver` struct; `apply_cluster_class` uses\n  the module-level
          `CLUSTER_CLASS_NAME` directly\n\n### Changed: `src/lib.rs`\n\n- `CLUSTER_CLASS_NAME`
          is now `LazyLock<String>` = `magnum-{VERGEN_GIT_DESCRIBE}` \u2014\n  each
          build gets a unique name derived from `git describe`\n- Exposed as `magnum_cluster_api.CLUSTER_CLASS_NAME`
          to Python\n\n### Changed: `build.rs`\n\nAdded `vergen-gix` emission so `VERGEN_GIT_DESCRIBE`
          is available at compile time.\n\n### Changed: `magnum_cluster_api/resources.py`\n\n-
          Removed `CLUSTER_CLASS_VERSION` / `CLUSTER_CLASS_NAME` constants and `importlib.metadata`\n-
          `Cluster.__init__` now takes a **required** `rust_driver` parameter\n- Removed
          `_resolve_immutable_fields` wrapper method\n- `get_object()` calls `self.rust_driver.resolve_immutable_fields()`
          directly instead of\n  conditionally building `api_server_load_balancer`
          dict from labels\n- Topology class references `magnum_cluster_api.CLUSTER_CLASS_NAME`
          (from Rust)\n\n### Changed: `magnum_cluster_api/driver.py`\n\n- `BaseDriver.__init__`
          passes only `namespace` to `Driver()` (no more `cluster_class_name`)\n-
          All four `resources.Cluster()` call sites (create, status check, update,
          delete) now\n  pass `rust_driver=self.rust_driver`\n\n### Changed: `release-please-config.json`
          / `pyproject.toml`\n\n- Switched to `release-type: rust` so `Cargo.toml`
          is the version source of truth\n- `pyproject.toml` version is now `dynamic
          = [\"version\"]` (maturin reads from Cargo.toml)\n\n### Changed: tests\n\n-
          `conftest.py`: `mock_rust_driver` fixture patches `Driver` with a passthrough\n
          \ `resolve_immutable_fields` lambda; removed `cluster_topology_variable`
          fixture\n  (no longer has consumers)\n- `test_resources.py`: removed `test_octavia_label_sets_provider`
          and\n  `test_no_octavia_label_omits_provider` (label\u2192variable logic
          is now Rust-only,\n  tested by the 15 Rust unit tests)\n- `test_driver.py`:
          added `rust_driver=ubuntu_driver.rust_driver` to\n  `resources.Cluster()`
          in assertion\n- `functional/fixtures.py`: `ClusterFixture` creates `Driver`
          once, passes it as\n  `rust_driver` to `Cluster` and reuses it for `apply_cluster_class()`\n"
        change_url: https://github.com/vexxhost/magnum-cluster-api/pull/956
        commit_id: 117eb7573d266bd4e42c46b8582806c76c0b460a
        patchset: 117eb7573d266bd4e42c46b8582806c76c0b460a
        project:
          canonical_hostname: github.com
          canonical_name: github.com/vexxhost/magnum-cluster-api
          name: vexxhost/magnum-cluster-api
          short_name: magnum-cluster-api
          src_dir: src/github.com/vexxhost/magnum-cluster-api
        topic: null
      job: magnum-cluster-api-hydrophone-v1.35.3-cilium
      jobtags: []
      max_attempts: 3
      message: Zml4OiBwcmVzZXJ2ZSBpbW11dGFibGUgT3BlblN0YWNrQ2x1c3RlciBmaWVsZHMgYW5kIHZlcnNpb24gY2x1c3RlciBjbGFzcyBuYW1lcwoKIyMgUHJvYmxlbQoKQ0FQSSdzIHRvcG9sb2d5IGNvbnRyb2xsZXIgYXBwbGllcyBKU09OIHBhdGNoZXMgYnkgcmVwbGFjaW5nIGVudGlyZSBvYmplY3RzCihlLmcuIGBhcGlTZXJ2ZXJMb2FkQmFsYW5jZXJgKSwgbm90IG1lcmdpbmcgaW5kaXZpZHVhbCBmaWVsZHMuIFByZXZpb3VzbHksCmByZXNvdXJjZXMucHlgIG9ubHkgaW5jbHVkZWQgb3B0aW9uYWwgZmllbGRzIGxpa2UgYHByb3ZpZGVyYCwgYGZsYXZvcmAsIGFuZApgYXZhaWxhYmlsaXR5Wm9uZWAgd2hlbiB0aGVpciBjb3JyZXNwb25kaW5nIGxhYmVscyB3ZXJlIHNldC4gT24gc3Vic2VxdWVudAp1cGRhdGVzIHdoZXJlIHRob3NlIGxhYmVscyBhcmUgYWJzZW50LCBDQVBJIHJlcGxhY2VzIHRoZSB3aG9sZSBvYmplY3Qgd2l0aCBvbmUKbWlzc2luZyB0aG9zZSBmaWVsZHMg4oCUIHRyaWdnZXJpbmcgaW1tdXRhYmxlLWZpZWxkIHZhbGlkYXRpb24gZXJyb3JzIG9uIHRoZQpleGlzdGluZyBgT3BlblN0YWNrQ2x1c3RlcmAuCgpTZXBhcmF0ZWx5LCBkZXYvUFIgYnVpbGRzIHVzZWQgYGltcG9ydGxpYi5tZXRhZGF0YS52ZXJzaW9uKClgIGZvciB0aGUgY2x1c3RlcgpjbGFzcyBuYW1lIChgbWFnbnVtLXYwLjM2LjJgKSwgc28gbm9uLXJlbGVhc2UgYnVpbGRzIHdvdWxkIGNvbGxpZGUgd2l0aCB0aGUKcmVsZWFzZSB2ZXJzaW9uIGFuZCBoaXQgYE9wZW5TdGFja0NsdXN0ZXJUZW1wbGF0ZWAgaW1tdXRhYmxlIGVycm9ycy4KCiMjIENoYW5nZXMKCiMjIyBOZXc6IGBzcmMvaW1tdXRhYmxlX2ZpZWxkcy5yc2AKCkRhdGEtZHJpdmVuIGZpZWxkIG1hcHBpbmcgc3lzdGVtIHRoYXQgcmVhZHMgdGhlICoqZXhpc3RpbmcqKiBgT3BlblN0YWNrQ2x1c3RlcmAKcmVzb3VyY2UgZnJvbSB0aGUgSzhzIEFQSSBiZWZvcmUgcmVidWlsZGluZyB0b3BvbG9neSB2YXJpYWJsZXM6CgotIGBGaWVsZE1hcHBpbmdgIOKAlCBtYXBzIGEgcmVzb3VyY2UgSlNPTiBwb2ludGVyIChgL3NwZWMvYXBpU2VydmVyTG9hZEJhbGFuY2VyL3Byb3ZpZGVyYCkKICB0byBhIHZhcmlhYmxlIEpTT04gcG9pbnRlciAoYC9hcGlTZXJ2ZXJMb2FkQmFsYW5jZXIvcHJvdmlkZXJgKSB3aXRoIGEgbGFiZWwgZmFsbGJhY2sKLSBgUmVzb3VyY2VGaWVsZE1hcHBpbmdzPFQ+YCDigJQgZ2VuZXJpYyBvdmVyIGFueSBuYW1lc3BhY2VkIEs4cyByZXNvdXJjZTsgaGFuZGxlcwogIEFQSSBsaXN0LWJ5LWxhYmVsLCBzZXJpYWxpemF0aW9uLCBhbmQgZm9sZGluZyBmaWVsZCBtYXBwaW5ncyBvdmVyIHRoZSB2YXJpYWJsZXMKLSBgT1BFTlNUQUNLX0NMVVNURVJfRklFTERTYCDigJQgY29uc3QgbWFwcGluZyBmb3IgYHByb3ZpZGVyYCwgYGZsYXZvcmAsIGBhdmFpbGFiaWxpdHlab25lYAotIFJlc29sdXRpb24gcHJpb3JpdHk6IGV4aXN0aW5nIHJlc291cmNlIHZhbHVlIOKGkiBsYWJlbCBmYWxsYmFjayDihpIgb21pdAotIFVzZXMgYGpzb25wdHJgIGNyYXRlIGZvciBSRkMgNjkwMSBwb2ludGVyIHJlc29sdmUvYXNzaWduCi0gMTUgdW5pdCB0ZXN0cyBhY3Jvc3MgYHBhcnNlX3BvaW50ZXJgLCBgZmllbGRfbWFwcGluZ2AsIGFuZCBgb3BlbnN0YWNrX2NsdXN0ZXJgIG1vZHVsZXMKCiMjIyBOZXc6IGBzcmMvY2x1c3Rlcl9hcGkvb3BlbnN0YWNrY2x1c3RlcnMucnNgCgprb3BpdW0tZ2VuZXJhdGVkIHR5cGVkIGBPcGVuU3RhY2tDbHVzdGVyYCBDUkQgKENBUE8gdjAuMTEuNikgZW5hYmxpbmcKYEFwaTxPcGVuU3RhY2tDbHVzdGVyPmAgZm9yIHR5cGUtc2FmZSBLOHMgQVBJIGNhbGxzIGluIHRoZSBmaWVsZCByZXNvbHZlci4KCiMjIyBDaGFuZ2VkOiBgc3JjL2RyaXZlci5yc2AKCi0gTmV3IGByZXNvbHZlX2ltbXV0YWJsZV9maWVsZHNgIHB5bWV0aG9kOiBkZXNlcmlhbGl6ZXMgUHl0aG9uIGRpY3Qg4oaSIGBzZXJkZV9qc29uOjpWYWx1ZWAsCiAgY2FsbHMgYE9QRU5TVEFDS19DTFVTVEVSX0ZJRUxEUy5yZXNvbHZlKClgIHZpYSB0b2tpbyBydW50aW1lLCByZXR1cm5zIHJlc3VsdCB0byBQeXRob24KLSBgY3JlYXRlX2V4Y2VwdGlvbiEoSW1tdXRhYmxlRmllbGRFcnJvcilgICsgYEZyb208aW1tdXRhYmxlX2ZpZWxkczo6RXJyb3I+IGZvciBQeUVycmAg4oCUCiAgUHlPMyBlcnJvciBib3VuZGFyeSBsaXZlcyBoZXJlLCBrZWVwaW5nIGBpbW11dGFibGVfZmllbGRzLnJzYCBmcmVlIG9mIHB5bzMgZGVwcwotIFJlbW92ZWQgYGNsdXN0ZXJfY2xhc3NfbmFtZWAgZmllbGQgZnJvbSBgRHJpdmVyYCBzdHJ1Y3Q7IGBhcHBseV9jbHVzdGVyX2NsYXNzYCB1c2VzCiAgdGhlIG1vZHVsZS1sZXZlbCBgQ0xVU1RFUl9DTEFTU19OQU1FYCBkaXJlY3RseQoKIyMjIENoYW5nZWQ6IGBzcmMvbGliLnJzYAoKLSBgQ0xVU1RFUl9DTEFTU19OQU1FYCBpcyBub3cgYExhenlMb2NrPFN0cmluZz5gID0gYG1hZ251bS17VkVSR0VOX0dJVF9ERVNDUklCRX1gIOKAlAogIGVhY2ggYnVpbGQgZ2V0cyBhIHVuaXF1ZSBuYW1lIGRlcml2ZWQgZnJvbSBgZ2l0IGRlc2NyaWJlYAotIEV4cG9zZWQgYXMgYG1hZ251bV9jbHVzdGVyX2FwaS5DTFVTVEVSX0NMQVNTX05BTUVgIHRvIFB5dGhvbgoKIyMjIENoYW5nZWQ6IGBidWlsZC5yc2AKCkFkZGVkIGB2ZXJnZW4tZ2l4YCBlbWlzc2lvbiBzbyBgVkVSR0VOX0dJVF9ERVNDUklCRWAgaXMgYXZhaWxhYmxlIGF0IGNvbXBpbGUgdGltZS4KCiMjIyBDaGFuZ2VkOiBgbWFnbnVtX2NsdXN0ZXJfYXBpL3Jlc291cmNlcy5weWAKCi0gUmVtb3ZlZCBgQ0xVU1RFUl9DTEFTU19WRVJTSU9OYCAvIGBDTFVTVEVSX0NMQVNTX05BTUVgIGNvbnN0YW50cyBhbmQgYGltcG9ydGxpYi5tZXRhZGF0YWAKLSBgQ2x1c3Rlci5fX2luaXRfX2Agbm93IHRha2VzIGEgKipyZXF1aXJlZCoqIGBydXN0X2RyaXZlcmAgcGFyYW1ldGVyCi0gUmVtb3ZlZCBgX3Jlc29sdmVfaW1tdXRhYmxlX2ZpZWxkc2Agd3JhcHBlciBtZXRob2QKLSBgZ2V0X29iamVjdCgpYCBjYWxscyBgc2VsZi5ydXN0X2RyaXZlci5yZXNvbHZlX2ltbXV0YWJsZV9maWVsZHMoKWAgZGlyZWN0bHkgaW5zdGVhZCBvZgogIGNvbmRpdGlvbmFsbHkgYnVpbGRpbmcgYGFwaV9zZXJ2ZXJfbG9hZF9iYWxhbmNlcmAgZGljdCBmcm9tIGxhYmVscwotIFRvcG9sb2d5IGNsYXNzIHJlZmVyZW5jZXMgYG1hZ251bV9jbHVzdGVyX2FwaS5DTFVTVEVSX0NMQVNTX05BTUVgIChmcm9tIFJ1c3QpCgojIyMgQ2hhbmdlZDogYG1hZ251bV9jbHVzdGVyX2FwaS9kcml2ZXIucHlgCgotIGBCYXNlRHJpdmVyLl9faW5pdF9fYCBwYXNzZXMgb25seSBgbmFtZXNwYWNlYCB0byBgRHJpdmVyKClgIChubyBtb3JlIGBjbHVzdGVyX2NsYXNzX25hbWVgKQotIEFsbCBmb3VyIGByZXNvdXJjZXMuQ2x1c3RlcigpYCBjYWxsIHNpdGVzIChjcmVhdGUsIHN0YXR1cyBjaGVjaywgdXBkYXRlLCBkZWxldGUpIG5vdwogIHBhc3MgYHJ1c3RfZHJpdmVyPXNlbGYucnVzdF9kcml2ZXJgCgojIyMgQ2hhbmdlZDogYHJlbGVhc2UtcGxlYXNlLWNvbmZpZy5qc29uYCAvIGBweXByb2plY3QudG9tbGAKCi0gU3dpdGNoZWQgdG8gYHJlbGVhc2UtdHlwZTogcnVzdGAgc28gYENhcmdvLnRvbWxgIGlzIHRoZSB2ZXJzaW9uIHNvdXJjZSBvZiB0cnV0aAotIGBweXByb2plY3QudG9tbGAgdmVyc2lvbiBpcyBub3cgYGR5bmFtaWMgPSBbInZlcnNpb24iXWAgKG1hdHVyaW4gcmVhZHMgZnJvbSBDYXJnby50b21sKQoKIyMjIENoYW5nZWQ6IHRlc3RzCgotIGBjb25mdGVzdC5weWA6IGBtb2NrX3J1c3RfZHJpdmVyYCBmaXh0dXJlIHBhdGNoZXMgYERyaXZlcmAgd2l0aCBhIHBhc3N0aHJvdWdoCiAgYHJlc29sdmVfaW1tdXRhYmxlX2ZpZWxkc2AgbGFtYmRhOyByZW1vdmVkIGBjbHVzdGVyX3RvcG9sb2d5X3ZhcmlhYmxlYCBmaXh0dXJlCiAgKG5vIGxvbmdlciBoYXMgY29uc3VtZXJzKQotIGB0ZXN0X3Jlc291cmNlcy5weWA6IHJlbW92ZWQgYHRlc3Rfb2N0YXZpYV9sYWJlbF9zZXRzX3Byb3ZpZGVyYCBhbmQKICBgdGVzdF9ub19vY3RhdmlhX2xhYmVsX29taXRzX3Byb3ZpZGVyYCAobGFiZWzihpJ2YXJpYWJsZSBsb2dpYyBpcyBub3cgUnVzdC1vbmx5LAogIHRlc3RlZCBieSB0aGUgMTUgUnVzdCB1bml0IHRlc3RzKQotIGB0ZXN0X2RyaXZlci5weWA6IGFkZGVkIGBydXN0X2RyaXZlcj11YnVudHVfZHJpdmVyLnJ1c3RfZHJpdmVyYCB0bwogIGByZXNvdXJjZXMuQ2x1c3RlcigpYCBpbiBhc3NlcnRpb24KLSBgZnVuY3Rpb25hbC9maXh0dXJlcy5weWA6IGBDbHVzdGVyRml4dHVyZWAgY3JlYXRlcyBgRHJpdmVyYCBvbmNlLCBwYXNzZXMgaXQgYXMKICBgcnVzdF9kcml2ZXJgIHRvIGBDbHVzdGVyYCBhbmQgcmV1c2VzIGl0IGZvciBgYXBwbHlfY2x1c3Rlcl9jbGFzcygpYAo=
      override_checkout: master
      patchset: 117eb7573d266bd4e42c46b8582806c76c0b460a
      pipeline: check
      playbook_context:
        playbook_projects:
          trusted/project_0/github.com/vexxhost/zuul-config:
            canonical_name: github.com/vexxhost/zuul-config
            checkout: main
            commit: 298983cd1253e6833abdb49d87d912527e0e6597
          trusted/project_1/opendev.org/zuul/zuul-jobs:
            canonical_name: opendev.org/zuul/zuul-jobs
            checkout: master
            commit: 01384e11271b1590fe57d1c69f228708f741103e
          trusted/project_2/github.com/vexxhost/zuul-jobs:
            canonical_name: github.com/vexxhost/zuul-jobs
            checkout: main
            commit: a6e68243e02ef030ce5e75f8b67630880c475f33
          untrusted/project_0/opendev.org/openstack/devstack:
            canonical_name: opendev.org/openstack/devstack
            checkout: master
            commit: 03ece8f88040be9b0b14dd1cfe93076ad2419a80
          untrusted/project_1/opendev.org/openstack/openstack-zuul-jobs:
            canonical_name: opendev.org/openstack/openstack-zuul-jobs
            checkout: master
            commit: 3d5175f90e389f3240a8400a792abaaeb51bee3b
          untrusted/project_2/github.com/vexxhost/zuul-config:
            canonical_name: github.com/vexxhost/zuul-config
            checkout: main
            commit: 298983cd1253e6833abdb49d87d912527e0e6597
          untrusted/project_3/opendev.org/zuul/zuul-jobs:
            canonical_name: opendev.org/zuul/zuul-jobs
            checkout: master
            commit: 01384e11271b1590fe57d1c69f228708f741103e
          untrusted/project_4/github.com/vexxhost/zuul-jobs:
            canonical_name: github.com/vexxhost/zuul-jobs
            checkout: main
            commit: a6e68243e02ef030ce5e75f8b67630880c475f33
          untrusted/project_5/github.com/vexxhost/magnum-cluster-api:
            canonical_name: github.com/vexxhost/magnum-cluster-api
            checkout: main
            commit: 117eb7573d266bd4e42c46b8582806c76c0b460a
        playbooks:
        - path: untrusted/project_5/github.com/vexxhost/magnum-cluster-api/zuul.d/playbooks/hydrophone/run.yml
          roles:
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/playbook_0/role_1/devstack
            link_target: untrusted/project_0/opendev.org/openstack/devstack
            role_path: ansible/playbook_0/role_1/devstack/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/playbook_0/role_2/openstack-zuul-jobs
            link_target: untrusted/project_1/opendev.org/openstack/openstack-zuul-jobs
            role_path: ansible/playbook_0/role_2/openstack-zuul-jobs/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/playbook_0/role_4/zuul-jobs
            link_target: untrusted/project_3/opendev.org/zuul/zuul-jobs
            role_path: ansible/playbook_0/role_4/zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/playbook_0/role_5/zuul-jobs
            link_target: untrusted/project_4/github.com/vexxhost/zuul-jobs
            role_path: ansible/playbook_0/role_5/zuul-jobs/roles
        post_playbooks:
        - path: untrusted/project_5/github.com/vexxhost/magnum-cluster-api/zuul.d/playbooks/hydrophone/post.yml
          roles:
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/post_playbook_0/role_1/devstack
            link_target: untrusted/project_0/opendev.org/openstack/devstack
            role_path: ansible/post_playbook_0/role_1/devstack/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/post_playbook_0/role_2/openstack-zuul-jobs
            link_target: untrusted/project_1/opendev.org/openstack/openstack-zuul-jobs
            role_path: ansible/post_playbook_0/role_2/openstack-zuul-jobs/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/post_playbook_0/role_4/zuul-jobs
            link_target: untrusted/project_3/opendev.org/zuul/zuul-jobs
            role_path: ansible/post_playbook_0/role_4/zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/post_playbook_0/role_5/zuul-jobs
            link_target: untrusted/project_4/github.com/vexxhost/zuul-jobs
            role_path: ansible/post_playbook_0/role_5/zuul-jobs/roles
        - path: untrusted/project_0/opendev.org/openstack/devstack/playbooks/post.yaml
          roles:
          - checkout: master
            checkout_description: playbook branch
            link_name: ansible/post_playbook_1/role_0/devstack
            link_target: untrusted/project_0/opendev.org/openstack/devstack
            role_path: ansible/post_playbook_1/role_0/devstack/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/post_playbook_1/role_1/openstack-zuul-jobs
            link_target: untrusted/project_1/opendev.org/openstack/openstack-zuul-jobs
            role_path: ansible/post_playbook_1/role_1/openstack-zuul-jobs/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/post_playbook_1/role_3/zuul-jobs
            link_target: untrusted/project_3/opendev.org/zuul/zuul-jobs
            role_path: ansible/post_playbook_1/role_3/zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/post_playbook_1/role_4/zuul-jobs
            link_target: untrusted/project_4/github.com/vexxhost/zuul-jobs
            role_path: ansible/post_playbook_1/role_4/zuul-jobs/roles
        - path: trusted/project_0/github.com/vexxhost/zuul-config/playbooks/base/post.yaml
          roles:
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/post_playbook_2/role_1/zuul-jobs
            link_target: trusted/project_1/opendev.org/zuul/zuul-jobs
            role_path: ansible/post_playbook_2/role_1/zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/post_playbook_2/role_2/zuul-jobs
            link_target: trusted/project_2/github.com/vexxhost/zuul-jobs
            role_path: ansible/post_playbook_2/role_2/zuul-jobs/roles
        - path: trusted/project_0/github.com/vexxhost/zuul-config/playbooks/base/post-logs.yaml
          roles:
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/post_playbook_3/role_1/zuul-jobs
            link_target: trusted/project_1/opendev.org/zuul/zuul-jobs
            role_path: ansible/post_playbook_3/role_1/zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/post_playbook_3/role_2/zuul-jobs
            link_target: trusted/project_2/github.com/vexxhost/zuul-jobs
            role_path: ansible/post_playbook_3/role_2/zuul-jobs/roles
        pre_playbooks:
        - path: trusted/project_0/github.com/vexxhost/zuul-config/playbooks/base/pre.yaml
          roles:
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/pre_playbook_0/role_1/zuul-jobs
            link_target: trusted/project_1/opendev.org/zuul/zuul-jobs
            role_path: ansible/pre_playbook_0/role_1/zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/pre_playbook_0/role_2/zuul-jobs
            link_target: trusted/project_2/github.com/vexxhost/zuul-jobs
            role_path: ansible/pre_playbook_0/role_2/zuul-jobs/roles
        - path: untrusted/project_0/opendev.org/openstack/devstack/playbooks/pre.yaml
          roles:
          - checkout: master
            checkout_description: playbook branch
            link_name: ansible/pre_playbook_1/role_0/devstack
            link_target: untrusted/project_0/opendev.org/openstack/devstack
            role_path: ansible/pre_playbook_1/role_0/devstack/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/pre_playbook_1/role_1/openstack-zuul-jobs
            link_target: untrusted/project_1/opendev.org/openstack/openstack-zuul-jobs
            role_path: ansible/pre_playbook_1/role_1/openstack-zuul-jobs/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/pre_playbook_1/role_3/zuul-jobs
            link_target: untrusted/project_3/opendev.org/zuul/zuul-jobs
            role_path: ansible/pre_playbook_1/role_3/zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/pre_playbook_1/role_4/zuul-jobs
            link_target: untrusted/project_4/github.com/vexxhost/zuul-jobs
            role_path: ansible/pre_playbook_1/role_4/zuul-jobs/roles
        - path: untrusted/project_5/github.com/vexxhost/magnum-cluster-api/zuul.d/playbooks/hydrophone/pre.yml
          roles:
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/pre_playbook_2/role_1/devstack
            link_target: untrusted/project_0/opendev.org/openstack/devstack
            role_path: ansible/pre_playbook_2/role_1/devstack/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/pre_playbook_2/role_2/openstack-zuul-jobs
            link_target: untrusted/project_1/opendev.org/openstack/openstack-zuul-jobs
            role_path: ansible/pre_playbook_2/role_2/openstack-zuul-jobs/roles
          - checkout: master
            checkout_description: job override ref
            link_name: ansible/pre_playbook_2/role_4/zuul-jobs
            link_target: untrusted/project_3/opendev.org/zuul/zuul-jobs
            role_path: ansible/pre_playbook_2/role_4/zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/pre_playbook_2/role_5/zuul-jobs
            link_target: untrusted/project_4/github.com/vexxhost/zuul-jobs
            role_path: ansible/pre_playbook_2/role_5/zuul-jobs/roles
      post_review: false
      post_timeout: null
      pre_timeout: null
      project:
        canonical_hostname: github.com
        canonical_name: github.com/vexxhost/magnum-cluster-api
        name: vexxhost/magnum-cluster-api
        short_name: magnum-cluster-api
        src_dir: src/github.com/vexxhost/magnum-cluster-api
      projects:
        github.com/novnc/novnc:
          canonical_hostname: github.com
          canonical_name: github.com/novnc/novnc
          checkout: master
          checkout_description: job override ref
          commit: 8e1ebdffba02e651c399dacef841f8941f6ad6e4
          name: novnc/novnc
          required: true
          short_name: novnc
          src_dir: src/github.com/novnc/novnc
        github.com/vexxhost/magnum-cluster-api:
          canonical_hostname: github.com
          canonical_name: github.com/vexxhost/magnum-cluster-api
          checkout: main
          checkout_description: zuul branch
          commit: 117eb7573d266bd4e42c46b8582806c76c0b460a
          name: vexxhost/magnum-cluster-api
          required: false
          short_name: magnum-cluster-api
          src_dir: src/github.com/vexxhost/magnum-cluster-api
        opendev.org/openstack/barbican:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/barbican
          checkout: master
          checkout_description: job override ref
          commit: f8a331a40eb21e6c8f37e07794d57aa98b120af9
          name: openstack/barbican
          required: true
          short_name: barbican
          src_dir: src/opendev.org/openstack/barbican
        opendev.org/openstack/cinder:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/cinder
          checkout: master
          checkout_description: job override ref
          commit: a707d2b4db22c346deb1d1b16c0607a43aac65d8
          name: openstack/cinder
          required: true
          short_name: cinder
          src_dir: src/opendev.org/openstack/cinder
        opendev.org/openstack/devstack:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/devstack
          checkout: master
          checkout_description: job override ref
          commit: 03ece8f88040be9b0b14dd1cfe93076ad2419a80
          name: openstack/devstack
          required: true
          short_name: devstack
          src_dir: src/opendev.org/openstack/devstack
        opendev.org/openstack/glance:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/glance
          checkout: master
          checkout_description: job override ref
          commit: 3f8cce1d7415d8358a9679c585ce3db32c3fde8e
          name: openstack/glance
          required: true
          short_name: glance
          src_dir: src/opendev.org/openstack/glance
        opendev.org/openstack/keystone:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/keystone
          checkout: master
          checkout_description: job override ref
          commit: 80d5b7bf50448073223723cf1f6001a367695e80
          name: openstack/keystone
          required: true
          short_name: keystone
          src_dir: src/opendev.org/openstack/keystone
        opendev.org/openstack/magnum:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/magnum
          checkout: master
          checkout_description: job override ref
          commit: 330321a64c846b5d4fa8b78d0fe1bcfe580413ce
          name: openstack/magnum
          required: true
          short_name: magnum
          src_dir: src/opendev.org/openstack/magnum
        opendev.org/openstack/manila:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/manila
          checkout: master
          checkout_description: job override ref
          commit: 201ac9b5bbdb9265dc0e442716709796b920fc6d
          name: openstack/manila
          required: true
          short_name: manila
          src_dir: src/opendev.org/openstack/manila
        opendev.org/openstack/neutron:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/neutron
          checkout: master
          checkout_description: job override ref
          commit: e70746fbdb6b1532445501300f2570694de12172
          name: openstack/neutron
          required: true
          short_name: neutron
          src_dir: src/opendev.org/openstack/neutron
        opendev.org/openstack/nova:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/nova
          checkout: master
          checkout_description: job override ref
          commit: 124e88eb1df0ad504212d90b974c846ff5719a70
          name: openstack/nova
          required: true
          short_name: nova
          src_dir: src/opendev.org/openstack/nova
        opendev.org/openstack/octavia:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/octavia
          checkout: master
          checkout_description: job override ref
          commit: c86b945c21b7d5d34cf13a4e9d52810d657682da
          name: openstack/octavia
          required: true
          short_name: octavia
          src_dir: src/opendev.org/openstack/octavia
        opendev.org/openstack/os-test-images:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/os-test-images
          checkout: master
          checkout_description: job override ref
          commit: 5d0367e03788764f41da8effffa14e3eac513201
          name: openstack/os-test-images
          required: true
          short_name: os-test-images
          src_dir: src/opendev.org/openstack/os-test-images
        opendev.org/openstack/ovn-octavia-provider:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/ovn-octavia-provider
          checkout: master
          checkout_description: job override ref
          commit: a04e63332c1a1fb2f1aceb20892f9aabefb75cf7
          name: openstack/ovn-octavia-provider
          required: true
          short_name: ovn-octavia-provider
          src_dir: src/opendev.org/openstack/ovn-octavia-provider
        opendev.org/openstack/placement:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/placement
          checkout: master
          checkout_description: job override ref
          commit: e3db398fba279721121892323e6260c6932797c1
          name: openstack/placement
          required: true
          short_name: placement
          src_dir: src/opendev.org/openstack/placement
        opendev.org/openstack/python-magnumclient:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/python-magnumclient
          checkout: master
          checkout_description: job override ref
          commit: bfc9dbc2aa9a113c12e591a87f774a6d986a981f
          name: openstack/python-magnumclient
          required: true
          short_name: python-magnumclient
          src_dir: src/opendev.org/openstack/python-magnumclient
        opendev.org/openstack/requirements:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/requirements
          checkout: master
          checkout_description: job override ref
          commit: 271d1a7861f04143f6b0eafedf885c9593cfa137
          name: openstack/requirements
          required: true
          short_name: requirements
          src_dir: src/opendev.org/openstack/requirements
        opendev.org/openstack/swift:
          canonical_hostname: opendev.org
          canonical_name: opendev.org/openstack/swift
          checkout: master
          checkout_description: job override ref
          commit: 0f23c3a97d762f4230f22e6c48bd444e2353806c
          name: openstack/swift
          required: true
          short_name: swift
          src_dir: src/opendev.org/openstack/swift
      ref: refs/pull/956/head
      resources: {}
      tenant: oss
      timeout: 7200
      topic: null
      voting: true
    zuul_copy_output:
      /etc/ceph: logs
      /etc/glusterfs/glusterd.vol: logs
      /etc/libvirt: logs
      /etc/lvm: logs
      /etc/resolv.conf: logs
      /etc/sudoers: logs
      /etc/sudoers.d: logs
      /var/log/ceph: logs
      /var/log/glusterfs: logs
      /var/log/libvirt: logs
      /var/log/mysql: logs
      /var/log/openvswitch: logs
      /var/log/postgresql: logs
      /var/log/rabbitmq: logs
      /var/log/unbound.log: logs
      '{{ devstack_conf_dir }}/.localrc.auto': logs
      '{{ devstack_conf_dir }}/.stackenv': logs
      '{{ devstack_conf_dir }}/local.conf': logs
      '{{ devstack_conf_dir }}/localrc': logs
      '{{ devstack_full_log}}': logs
      '{{ devstack_log_dir }}/atop': logs
      '{{ devstack_log_dir }}/devstacklog.txt': logs
      '{{ devstack_log_dir }}/devstacklog.txt.summary': logs
      '{{ devstack_log_dir }}/dstat-csv.log': logs
      '{{ devstack_log_dir }}/qemu.coredump': logs
      '{{ devstack_log_dir }}/tcpdump.pcap': logs
      '{{ devstack_log_dir }}/worlddump-latest.txt': logs
      '{{ stage_dir }}/apache': logs
      '{{ stage_dir }}/apache_config': logs
      '{{ stage_dir }}/audit.log': logs
      '{{ stage_dir }}/core': logs
      '{{ stage_dir }}/deprecations.log': logs
      '{{ stage_dir }}/df.txt': logs
      '{{ stage_dir }}/dpkg-l.txt': logs
      '{{ stage_dir }}/etc': logs
      '{{ stage_dir }}/iptables.txt': logs
      '{{ stage_dir }}/listen53.txt': logs
      '{{ stage_dir }}/mount.txt': logs
      '{{ stage_dir }}/performance.json': logs
      '{{ stage_dir }}/pip2-freeze.txt': logs
      '{{ stage_dir }}/pip3-freeze.txt': logs
      '{{ stage_dir }}/rpm-qa.txt': logs
      '{{ stage_dir }}/services.txt': logs
      '{{ stage_dir }}/verify_tempest_conf.log': logs
