all:
  children:
    tempest:
      hosts:
        controller: null
    zuul_unreachable:
      hosts: {}
  hosts:
    controller:
      ansible_connection: ssh
      ansible_host: 199.204.45.22
      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.34.7
      network_driver: calico
      nodepool:
        az: nova
        cloud: public
        external_id: 6d68032c-1762-48d8-ae76-fb8a49e6f04d
        host_id: 7cb77d063530dedbf6983b78a36ec607482cf1d282610499e8bd9357
        interface_ip: 199.204.45.22
        label: ubuntu-noble-16
        node_properties: {}
        private_ipv4: 199.204.45.22
        private_ipv6: null
        provider: yul1
        public_ipv4: 199.204.45.22
        public_ipv6: 2604:e100:1:0:f816:3eff:fe2e:20ca
        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: 6d68032c-1762-48d8-ae76-fb8a49e6f04d
        host_id: 7cb77d063530dedbf6983b78a36ec607482cf1d282610499e8bd9357
        interface_ip: 199.204.45.22
        label: ubuntu-noble-16
        node_properties: {}
        private_ipv4: 199.204.45.22
        private_ipv6: null
        provider: yul1
        public_ipv4: 199.204.45.22
        public_ipv6: 2604:e100:1:0:f816:3eff:fe2e:20ca
        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.34.7
    network_driver: calico
    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.34.7 explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: vexxhost/magnum-cluster-api/zuul.d/jobs.yaml@main#90>'
      - '<Job magnum-cluster-api-hydrophone-v1.34.7-calico explicit: None implied:
        {MatchAny:{ImpliedBranchMatcher:main}} source: vexxhost/magnum-cluster-api/zuul.d/jobs.yaml@main#96>'
      - '<Job magnum-cluster-api-hydrophone-v1.34.7-calico explicit: None implied:
        None source: vexxhost/magnum-cluster-api/zuul.d/project.yaml@main#1>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: 7fbc32c8c4ce4885bda53646df92fa92
      build_refs:
      - branch: main
        change: '1013'
        change_message: "feat: configure kubelet via kubeadm config patches\n\n##
          Problem\n\nBaremetal and GPU-oriented Kubernetes clusters need kubelet CPU,
          topology, and pod-density tuning through Magnum labels so the settings survive
          node replacement, scale-up, and rolling upgrades. The old alternatives are
          weak for production:\n\n- post-create SSH edits to `/var/lib/kubelet/config.yaml`
          are not declarative and do not survive replacement;\n- `kubeletExtraArgs`
          forwards command-line flags, but kubelet is moving these settings to structured
          configuration and the equivalent CLI flags are deprecated;\n- accepting
          arbitrary JSON/YAML from a Magnum label would make labels carry too much
          structured configuration and would be hard to validate safely.\n\n## Solution\n\nPR
          #1013 exposes a structured kubelet configuration path backed by operator-managed
          profiles.\n\nOperators define reusable kubelet profiles in the management
          Kubernetes cluster with this ConfigMap:\n\n```yaml\napiVersion: v1\nkind:
          ConfigMap\nmetadata:\n  name: mcapi-kubelet-config-profiles\n  namespace:
          magnum-system\ndata:\n  profile-gpu: |\n    cpuManagerPolicy: static\n    topologyManagerPolicy:
          single-numa-node\n    reservedSystemCPUs: 0-1\n    maxPods: 250\n```\n\nUsers
          select a predefined profile with `kubelet_config_profile=<name>`, then may
          override individual supported fields with typed labels at cluster creation
          time:\n\n| Label | Example | Effect |\n|---|---|---|\n| `kubelet_config_profile`
          | `profile-gpu` | Loads operator-defined defaults from `ConfigMap/mcapi-kubelet-config-profiles`.
          |\n| `kubelet_max_pods` | `250` | Sets kubelet `maxPods`. |\n| `kubelet_cpu_manager_policy`
          | `static` | Sets kubelet `cpuManagerPolicy`. Accepted values: `none`, `static`.
          |\n| `kubelet_topology_manager_policy` | `single-numa-node` | Sets kubelet
          `topologyManagerPolicy`. Accepted values: `none`, `best-effort`, `restricted`,
          `single-numa-node`. |\n| `kubelet_reserved_cpus` | `0-1` | Sets kubelet
          `reservedSystemCPUs`. |\n\nExplicit labels win over profile defaults.\n\nWhen
          a profile or any kubelet label is set, mcapi passes a `kubeletConfig` ClusterClass
          topology variable and renders `/etc/kubernetes/patches/kubeletconfiguration+merge.yaml`
          into both control-plane and worker kubeadm configs. The feature also sets
          the kubeadm patches directory to `/etc/kubernetes/patches` for init/join
          paths.\n\nmcapi validates the requested profile before creating the cluster.
          If the ConfigMap is missing, the profile name is unknown, the profile YAML
          is invalid, or the profile contains unsupported/invalid fields, cluster
          creation fails before CAPI resources are rendered.\n\nThe driver also merges
          any missing cluster-template labels into the sparse `cluster.labels` value
          that Magnum stores when users pass `--labels`, so required template labels
          such as `kube_tag` remain available to the Rust driver and later monitor/delete
          paths.\n\n## Usage\n\n```bash\nopenstack coe cluster create bm-gpu \\\n
          \ --cluster-template k8s-bm \\\n  --labels kubelet_max_pods=250 \\\n  --labels
          kubelet_cpu_manager_policy=static \\\n  --labels kubelet_topology_manager_policy=single-numa-node
          \\\n  --labels kubelet_reserved_cpus=0-1 \\\n  --labels kubelet_config_profile=profile-gpu\n```\n\nTo
          verify rendering before nodes are Ready, inspect the generated CAPI/bootstrap
          resources for:\n\n```yaml\npath: /etc/kubernetes/patches/kubeletconfiguration+merge.yaml\ncontent:
          |\n  apiVersion: kubelet.config.k8s.io/v1beta1\n  kind: KubeletConfiguration\n
          \ cpuManagerPolicy: static\n  topologyManagerPolicy: single-numa-node\n
          \ reservedSystemCPUs: 0-1\n  maxPods: 250\n```\n\nOnce nodes are Ready,
          verify the merged kubelet config on a node:\n\n```bash\nsudo grep -E 'cpuManagerPolicy|topologyManagerPolicy|reservedSystemCPUs|maxPods'
          /var/lib/kubelet/config.yaml\n```\n\nKubelet profile labels are selected
          when the cluster is created. I tested `openstack coe cluster update ...
          replace labels/kubelet_max_pods=240` on the AIO and Magnum rejects real
          label changes with `cannot change cluster property(ies) labels`, so the
          docs now call this out instead of documenting label update as supported.\n\n##
          Why profiles instead of arbitrary kubelet config labels?\n\nProfiles avoid
          turning Magnum labels into a large untyped config transport. Operators own
          the reusable kubelet policy in the management cluster, while users get a
          small and validated label surface for selecting a profile and overriding
          the fields mcapi intentionally supports.\n\nThis also avoids hardcoding
          deployment-specific profiles in mcapi config. The source of truth is a normal
          Kubernetes resource in the management cluster, so operators can update profile
          definitions without changing mcapi code or oslo configuration.\n\n## Tests\n\nLocal
          validation:\n\n```bash\nuv run --python 3.10 pytest magnum_cluster_api/tests/unit/test_utils.py::TestKubeletConfigLabels
          magnum_cluster_api/tests/unit/test_utils.py::TestFillMissingLabelsFromTemplate
          magnum_cluster_api/tests/unit/test_resources.py magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_create_cluster
          magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_update_cluster_applies_topology_changes
          magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_update_cluster_merges_sparse_labels\ncargo
          test kubelet_config\ncargo test test_convert_values_to_cluster_topology_variables\nuvx
          pre-commit run --all-files\nuvx --with mkdocs-material --with mkdocs-literate-nav
          mkdocs build --strict\ngit diff --check HEAD\nrustfmt --check src/features/kubelet_config.rs\nuv
          run --python 3.10 python -m compileall -q magnum_cluster_api\n```\n\nResults:
          all passed.\n\nAIO OVN validation on `38.108.68.110`:\n\n- Rolled Magnum
          API, conductor, and `magnum-cluster-api-proxy` to a temporary local image
          built from this PR commit.\n- Created `ConfigMap/mcapi-kubelet-config-profiles`
          in `magnum-system` with `profile-gpu`.\n- Created a test cluster with `kubelet_config_profile=profile-gpu`
          plus explicit `kubelet_*` labels.\n- Confirmed the profile code loaded in
          the conductor and the ClusterClass rendered the `kubeletConfig` patch and
          schema.\n- Found and fixed the sparse-label live-path issue where user `--labels`
          replaced template labels and left the Rust driver without `kube_tag`.\n-
          Re-tested Magnum label update: a no-op replace of the existing `kubelet_config_profile=profile-gpu`
          was accepted, but changing `labels/kubelet_max_pods=240` was rejected by
          Magnum API with HTTP 400 `cannot change cluster property(ies) labels`; docs
          were updated to state kubelet labels are create-time settings.\n- Full CAPI
          Cluster creation is currently blocked by existing AIO OpenStackSDK compatibility
          issues outside this PR path, first in Magnum API validation and then in
          conductor helper calls such as `osc.cinder().volume_types`.\n- Restored
          Magnum API, conductor, and `magnum-cluster-api-proxy` to `ghcr.io/vexxhost/magnum:main@sha256:be30fc62b97ee15502c211cc1c73ae698a47d9ea7d5982a396db1d677f2088aa`
          after testing."
        change_url: https://github.com/vexxhost/magnum-cluster-api/pull/1013
        commit_id: 4293b702fdcd4e96f2c1b94dc295d6e7622dace2
        patchset: 4293b702fdcd4e96f2c1b94dc295d6e7622dace2
        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: f51b938d4f594935b242135d8fd88cbf
      buildset_refs:
      - branch: main
        change: '1013'
        change_message: "feat: configure kubelet via kubeadm config patches\n\n##
          Problem\n\nBaremetal and GPU-oriented Kubernetes clusters need kubelet CPU,
          topology, and pod-density tuning through Magnum labels so the settings survive
          node replacement, scale-up, and rolling upgrades. The old alternatives are
          weak for production:\n\n- post-create SSH edits to `/var/lib/kubelet/config.yaml`
          are not declarative and do not survive replacement;\n- `kubeletExtraArgs`
          forwards command-line flags, but kubelet is moving these settings to structured
          configuration and the equivalent CLI flags are deprecated;\n- accepting
          arbitrary JSON/YAML from a Magnum label would make labels carry too much
          structured configuration and would be hard to validate safely.\n\n## Solution\n\nPR
          #1013 exposes a structured kubelet configuration path backed by operator-managed
          profiles.\n\nOperators define reusable kubelet profiles in the management
          Kubernetes cluster with this ConfigMap:\n\n```yaml\napiVersion: v1\nkind:
          ConfigMap\nmetadata:\n  name: mcapi-kubelet-config-profiles\n  namespace:
          magnum-system\ndata:\n  profile-gpu: |\n    cpuManagerPolicy: static\n    topologyManagerPolicy:
          single-numa-node\n    reservedSystemCPUs: 0-1\n    maxPods: 250\n```\n\nUsers
          select a predefined profile with `kubelet_config_profile=<name>`, then may
          override individual supported fields with typed labels at cluster creation
          time:\n\n| Label | Example | Effect |\n|---|---|---|\n| `kubelet_config_profile`
          | `profile-gpu` | Loads operator-defined defaults from `ConfigMap/mcapi-kubelet-config-profiles`.
          |\n| `kubelet_max_pods` | `250` | Sets kubelet `maxPods`. |\n| `kubelet_cpu_manager_policy`
          | `static` | Sets kubelet `cpuManagerPolicy`. Accepted values: `none`, `static`.
          |\n| `kubelet_topology_manager_policy` | `single-numa-node` | Sets kubelet
          `topologyManagerPolicy`. Accepted values: `none`, `best-effort`, `restricted`,
          `single-numa-node`. |\n| `kubelet_reserved_cpus` | `0-1` | Sets kubelet
          `reservedSystemCPUs`. |\n\nExplicit labels win over profile defaults.\n\nWhen
          a profile or any kubelet label is set, mcapi passes a `kubeletConfig` ClusterClass
          topology variable and renders `/etc/kubernetes/patches/kubeletconfiguration+merge.yaml`
          into both control-plane and worker kubeadm configs. The feature also sets
          the kubeadm patches directory to `/etc/kubernetes/patches` for init/join
          paths.\n\nmcapi validates the requested profile before creating the cluster.
          If the ConfigMap is missing, the profile name is unknown, the profile YAML
          is invalid, or the profile contains unsupported/invalid fields, cluster
          creation fails before CAPI resources are rendered.\n\nThe driver also merges
          any missing cluster-template labels into the sparse `cluster.labels` value
          that Magnum stores when users pass `--labels`, so required template labels
          such as `kube_tag` remain available to the Rust driver and later monitor/delete
          paths.\n\n## Usage\n\n```bash\nopenstack coe cluster create bm-gpu \\\n
          \ --cluster-template k8s-bm \\\n  --labels kubelet_max_pods=250 \\\n  --labels
          kubelet_cpu_manager_policy=static \\\n  --labels kubelet_topology_manager_policy=single-numa-node
          \\\n  --labels kubelet_reserved_cpus=0-1 \\\n  --labels kubelet_config_profile=profile-gpu\n```\n\nTo
          verify rendering before nodes are Ready, inspect the generated CAPI/bootstrap
          resources for:\n\n```yaml\npath: /etc/kubernetes/patches/kubeletconfiguration+merge.yaml\ncontent:
          |\n  apiVersion: kubelet.config.k8s.io/v1beta1\n  kind: KubeletConfiguration\n
          \ cpuManagerPolicy: static\n  topologyManagerPolicy: single-numa-node\n
          \ reservedSystemCPUs: 0-1\n  maxPods: 250\n```\n\nOnce nodes are Ready,
          verify the merged kubelet config on a node:\n\n```bash\nsudo grep -E 'cpuManagerPolicy|topologyManagerPolicy|reservedSystemCPUs|maxPods'
          /var/lib/kubelet/config.yaml\n```\n\nKubelet profile labels are selected
          when the cluster is created. I tested `openstack coe cluster update ...
          replace labels/kubelet_max_pods=240` on the AIO and Magnum rejects real
          label changes with `cannot change cluster property(ies) labels`, so the
          docs now call this out instead of documenting label update as supported.\n\n##
          Why profiles instead of arbitrary kubelet config labels?\n\nProfiles avoid
          turning Magnum labels into a large untyped config transport. Operators own
          the reusable kubelet policy in the management cluster, while users get a
          small and validated label surface for selecting a profile and overriding
          the fields mcapi intentionally supports.\n\nThis also avoids hardcoding
          deployment-specific profiles in mcapi config. The source of truth is a normal
          Kubernetes resource in the management cluster, so operators can update profile
          definitions without changing mcapi code or oslo configuration.\n\n## Tests\n\nLocal
          validation:\n\n```bash\nuv run --python 3.10 pytest magnum_cluster_api/tests/unit/test_utils.py::TestKubeletConfigLabels
          magnum_cluster_api/tests/unit/test_utils.py::TestFillMissingLabelsFromTemplate
          magnum_cluster_api/tests/unit/test_resources.py magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_create_cluster
          magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_update_cluster_applies_topology_changes
          magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_update_cluster_merges_sparse_labels\ncargo
          test kubelet_config\ncargo test test_convert_values_to_cluster_topology_variables\nuvx
          pre-commit run --all-files\nuvx --with mkdocs-material --with mkdocs-literate-nav
          mkdocs build --strict\ngit diff --check HEAD\nrustfmt --check src/features/kubelet_config.rs\nuv
          run --python 3.10 python -m compileall -q magnum_cluster_api\n```\n\nResults:
          all passed.\n\nAIO OVN validation on `38.108.68.110`:\n\n- Rolled Magnum
          API, conductor, and `magnum-cluster-api-proxy` to a temporary local image
          built from this PR commit.\n- Created `ConfigMap/mcapi-kubelet-config-profiles`
          in `magnum-system` with `profile-gpu`.\n- Created a test cluster with `kubelet_config_profile=profile-gpu`
          plus explicit `kubelet_*` labels.\n- Confirmed the profile code loaded in
          the conductor and the ClusterClass rendered the `kubeletConfig` patch and
          schema.\n- Found and fixed the sparse-label live-path issue where user `--labels`
          replaced template labels and left the Rust driver without `kube_tag`.\n-
          Re-tested Magnum label update: a no-op replace of the existing `kubelet_config_profile=profile-gpu`
          was accepted, but changing `labels/kubelet_max_pods=240` was rejected by
          Magnum API with HTTP 400 `cannot change cluster property(ies) labels`; docs
          were updated to state kubelet labels are create-time settings.\n- Full CAPI
          Cluster creation is currently blocked by existing AIO OpenStackSDK compatibility
          issues outside this PR path, first in Magnum API validation and then in
          conductor helper calls such as `osc.cinder().volume_types`.\n- Restored
          Magnum API, conductor, and `magnum-cluster-api-proxy` to `ghcr.io/vexxhost/magnum:main@sha256:be30fc62b97ee15502c211cc1c73ae698a47d9ea7d5982a396db1d677f2088aa`
          after testing."
        change_url: https://github.com/vexxhost/magnum-cluster-api/pull/1013
        commit_id: 4293b702fdcd4e96f2c1b94dc295d6e7622dace2
        patchset: 4293b702fdcd4e96f2c1b94dc295d6e7622dace2
        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: '1013'
      change_message: "feat: configure kubelet via kubeadm config patches\n\n## Problem\n\nBaremetal
        and GPU-oriented Kubernetes clusters need kubelet CPU, topology, and pod-density
        tuning through Magnum labels so the settings survive node replacement, scale-up,
        and rolling upgrades. The old alternatives are weak for production:\n\n- post-create
        SSH edits to `/var/lib/kubelet/config.yaml` are not declarative and do not
        survive replacement;\n- `kubeletExtraArgs` forwards command-line flags, but
        kubelet is moving these settings to structured configuration and the equivalent
        CLI flags are deprecated;\n- accepting arbitrary JSON/YAML from a Magnum label
        would make labels carry too much structured configuration and would be hard
        to validate safely.\n\n## Solution\n\nPR #1013 exposes a structured kubelet
        configuration path backed by operator-managed profiles.\n\nOperators define
        reusable kubelet profiles in the management Kubernetes cluster with this ConfigMap:\n\n```yaml\napiVersion:
        v1\nkind: ConfigMap\nmetadata:\n  name: mcapi-kubelet-config-profiles\n  namespace:
        magnum-system\ndata:\n  profile-gpu: |\n    cpuManagerPolicy: static\n    topologyManagerPolicy:
        single-numa-node\n    reservedSystemCPUs: 0-1\n    maxPods: 250\n```\n\nUsers
        select a predefined profile with `kubelet_config_profile=<name>`, then may
        override individual supported fields with typed labels at cluster creation
        time:\n\n| Label | Example | Effect |\n|---|---|---|\n| `kubelet_config_profile`
        | `profile-gpu` | Loads operator-defined defaults from `ConfigMap/mcapi-kubelet-config-profiles`.
        |\n| `kubelet_max_pods` | `250` | Sets kubelet `maxPods`. |\n| `kubelet_cpu_manager_policy`
        | `static` | Sets kubelet `cpuManagerPolicy`. Accepted values: `none`, `static`.
        |\n| `kubelet_topology_manager_policy` | `single-numa-node` | Sets kubelet
        `topologyManagerPolicy`. Accepted values: `none`, `best-effort`, `restricted`,
        `single-numa-node`. |\n| `kubelet_reserved_cpus` | `0-1` | Sets kubelet `reservedSystemCPUs`.
        |\n\nExplicit labels win over profile defaults.\n\nWhen a profile or any kubelet
        label is set, mcapi passes a `kubeletConfig` ClusterClass topology variable
        and renders `/etc/kubernetes/patches/kubeletconfiguration+merge.yaml` into
        both control-plane and worker kubeadm configs. The feature also sets the kubeadm
        patches directory to `/etc/kubernetes/patches` for init/join paths.\n\nmcapi
        validates the requested profile before creating the cluster. If the ConfigMap
        is missing, the profile name is unknown, the profile YAML is invalid, or the
        profile contains unsupported/invalid fields, cluster creation fails before
        CAPI resources are rendered.\n\nThe driver also merges any missing cluster-template
        labels into the sparse `cluster.labels` value that Magnum stores when users
        pass `--labels`, so required template labels such as `kube_tag` remain available
        to the Rust driver and later monitor/delete paths.\n\n## Usage\n\n```bash\nopenstack
        coe cluster create bm-gpu \\\n  --cluster-template k8s-bm \\\n  --labels kubelet_max_pods=250
        \\\n  --labels kubelet_cpu_manager_policy=static \\\n  --labels kubelet_topology_manager_policy=single-numa-node
        \\\n  --labels kubelet_reserved_cpus=0-1 \\\n  --labels kubelet_config_profile=profile-gpu\n```\n\nTo
        verify rendering before nodes are Ready, inspect the generated CAPI/bootstrap
        resources for:\n\n```yaml\npath: /etc/kubernetes/patches/kubeletconfiguration+merge.yaml\ncontent:
        |\n  apiVersion: kubelet.config.k8s.io/v1beta1\n  kind: KubeletConfiguration\n
        \ cpuManagerPolicy: static\n  topologyManagerPolicy: single-numa-node\n  reservedSystemCPUs:
        0-1\n  maxPods: 250\n```\n\nOnce nodes are Ready, verify the merged kubelet
        config on a node:\n\n```bash\nsudo grep -E 'cpuManagerPolicy|topologyManagerPolicy|reservedSystemCPUs|maxPods'
        /var/lib/kubelet/config.yaml\n```\n\nKubelet profile labels are selected when
        the cluster is created. I tested `openstack coe cluster update ... replace
        labels/kubelet_max_pods=240` on the AIO and Magnum rejects real label changes
        with `cannot change cluster property(ies) labels`, so the docs now call this
        out instead of documenting label update as supported.\n\n## Why profiles instead
        of arbitrary kubelet config labels?\n\nProfiles avoid turning Magnum labels
        into a large untyped config transport. Operators own the reusable kubelet
        policy in the management cluster, while users get a small and validated label
        surface for selecting a profile and overriding the fields mcapi intentionally
        supports.\n\nThis also avoids hardcoding deployment-specific profiles in mcapi
        config. The source of truth is a normal Kubernetes resource in the management
        cluster, so operators can update profile definitions without changing mcapi
        code or oslo configuration.\n\n## Tests\n\nLocal validation:\n\n```bash\nuv
        run --python 3.10 pytest magnum_cluster_api/tests/unit/test_utils.py::TestKubeletConfigLabels
        magnum_cluster_api/tests/unit/test_utils.py::TestFillMissingLabelsFromTemplate
        magnum_cluster_api/tests/unit/test_resources.py magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_create_cluster
        magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_update_cluster_applies_topology_changes
        magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_update_cluster_merges_sparse_labels\ncargo
        test kubelet_config\ncargo test test_convert_values_to_cluster_topology_variables\nuvx
        pre-commit run --all-files\nuvx --with mkdocs-material --with mkdocs-literate-nav
        mkdocs build --strict\ngit diff --check HEAD\nrustfmt --check src/features/kubelet_config.rs\nuv
        run --python 3.10 python -m compileall -q magnum_cluster_api\n```\n\nResults:
        all passed.\n\nAIO OVN validation on `38.108.68.110`:\n\n- Rolled Magnum API,
        conductor, and `magnum-cluster-api-proxy` to a temporary local image built
        from this PR commit.\n- Created `ConfigMap/mcapi-kubelet-config-profiles`
        in `magnum-system` with `profile-gpu`.\n- Created a test cluster with `kubelet_config_profile=profile-gpu`
        plus explicit `kubelet_*` labels.\n- Confirmed the profile code loaded in
        the conductor and the ClusterClass rendered the `kubeletConfig` patch and
        schema.\n- Found and fixed the sparse-label live-path issue where user `--labels`
        replaced template labels and left the Rust driver without `kube_tag`.\n- Re-tested
        Magnum label update: a no-op replace of the existing `kubelet_config_profile=profile-gpu`
        was accepted, but changing `labels/kubelet_max_pods=240` was rejected by Magnum
        API with HTTP 400 `cannot change cluster property(ies) labels`; docs were
        updated to state kubelet labels are create-time settings.\n- Full CAPI Cluster
        creation is currently blocked by existing AIO OpenStackSDK compatibility issues
        outside this PR path, first in Magnum API validation and then in conductor
        helper calls such as `osc.cinder().volume_types`.\n- Restored Magnum API,
        conductor, and `magnum-cluster-api-proxy` to `ghcr.io/vexxhost/magnum:main@sha256:be30fc62b97ee15502c211cc1c73ae698a47d9ea7d5982a396db1d677f2088aa`
        after testing."
      change_url: https://github.com/vexxhost/magnum-cluster-api/pull/1013
      child_jobs: []
      commit_id: 4293b702fdcd4e96f2c1b94dc295d6e7622dace2
      event_id: 95087d80-5404-11f1-85b3-9550ae0d915a
      executor:
        hostname: 2d72f0692154
        inventory_file: /var/lib/zuul/builds/7fbc32c8c4ce4885bda53646df92fa92/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/7fbc32c8c4ce4885bda53646df92fa92/work/logs
        result_data_file: /var/lib/zuul/builds/7fbc32c8c4ce4885bda53646df92fa92/work/results.json
        src_root: /var/lib/zuul/builds/7fbc32c8c4ce4885bda53646df92fa92/work/src
        work_root: /var/lib/zuul/builds/7fbc32c8c4ce4885bda53646df92fa92/work
      include_vars: []
      items:
      - branch: main
        change: '1013'
        change_message: "feat: configure kubelet via kubeadm config patches\n\n##
          Problem\n\nBaremetal and GPU-oriented Kubernetes clusters need kubelet CPU,
          topology, and pod-density tuning through Magnum labels so the settings survive
          node replacement, scale-up, and rolling upgrades. The old alternatives are
          weak for production:\n\n- post-create SSH edits to `/var/lib/kubelet/config.yaml`
          are not declarative and do not survive replacement;\n- `kubeletExtraArgs`
          forwards command-line flags, but kubelet is moving these settings to structured
          configuration and the equivalent CLI flags are deprecated;\n- accepting
          arbitrary JSON/YAML from a Magnum label would make labels carry too much
          structured configuration and would be hard to validate safely.\n\n## Solution\n\nPR
          #1013 exposes a structured kubelet configuration path backed by operator-managed
          profiles.\n\nOperators define reusable kubelet profiles in the management
          Kubernetes cluster with this ConfigMap:\n\n```yaml\napiVersion: v1\nkind:
          ConfigMap\nmetadata:\n  name: mcapi-kubelet-config-profiles\n  namespace:
          magnum-system\ndata:\n  profile-gpu: |\n    cpuManagerPolicy: static\n    topologyManagerPolicy:
          single-numa-node\n    reservedSystemCPUs: 0-1\n    maxPods: 250\n```\n\nUsers
          select a predefined profile with `kubelet_config_profile=<name>`, then may
          override individual supported fields with typed labels at cluster creation
          time:\n\n| Label | Example | Effect |\n|---|---|---|\n| `kubelet_config_profile`
          | `profile-gpu` | Loads operator-defined defaults from `ConfigMap/mcapi-kubelet-config-profiles`.
          |\n| `kubelet_max_pods` | `250` | Sets kubelet `maxPods`. |\n| `kubelet_cpu_manager_policy`
          | `static` | Sets kubelet `cpuManagerPolicy`. Accepted values: `none`, `static`.
          |\n| `kubelet_topology_manager_policy` | `single-numa-node` | Sets kubelet
          `topologyManagerPolicy`. Accepted values: `none`, `best-effort`, `restricted`,
          `single-numa-node`. |\n| `kubelet_reserved_cpus` | `0-1` | Sets kubelet
          `reservedSystemCPUs`. |\n\nExplicit labels win over profile defaults.\n\nWhen
          a profile or any kubelet label is set, mcapi passes a `kubeletConfig` ClusterClass
          topology variable and renders `/etc/kubernetes/patches/kubeletconfiguration+merge.yaml`
          into both control-plane and worker kubeadm configs. The feature also sets
          the kubeadm patches directory to `/etc/kubernetes/patches` for init/join
          paths.\n\nmcapi validates the requested profile before creating the cluster.
          If the ConfigMap is missing, the profile name is unknown, the profile YAML
          is invalid, or the profile contains unsupported/invalid fields, cluster
          creation fails before CAPI resources are rendered.\n\nThe driver also merges
          any missing cluster-template labels into the sparse `cluster.labels` value
          that Magnum stores when users pass `--labels`, so required template labels
          such as `kube_tag` remain available to the Rust driver and later monitor/delete
          paths.\n\n## Usage\n\n```bash\nopenstack coe cluster create bm-gpu \\\n
          \ --cluster-template k8s-bm \\\n  --labels kubelet_max_pods=250 \\\n  --labels
          kubelet_cpu_manager_policy=static \\\n  --labels kubelet_topology_manager_policy=single-numa-node
          \\\n  --labels kubelet_reserved_cpus=0-1 \\\n  --labels kubelet_config_profile=profile-gpu\n```\n\nTo
          verify rendering before nodes are Ready, inspect the generated CAPI/bootstrap
          resources for:\n\n```yaml\npath: /etc/kubernetes/patches/kubeletconfiguration+merge.yaml\ncontent:
          |\n  apiVersion: kubelet.config.k8s.io/v1beta1\n  kind: KubeletConfiguration\n
          \ cpuManagerPolicy: static\n  topologyManagerPolicy: single-numa-node\n
          \ reservedSystemCPUs: 0-1\n  maxPods: 250\n```\n\nOnce nodes are Ready,
          verify the merged kubelet config on a node:\n\n```bash\nsudo grep -E 'cpuManagerPolicy|topologyManagerPolicy|reservedSystemCPUs|maxPods'
          /var/lib/kubelet/config.yaml\n```\n\nKubelet profile labels are selected
          when the cluster is created. I tested `openstack coe cluster update ...
          replace labels/kubelet_max_pods=240` on the AIO and Magnum rejects real
          label changes with `cannot change cluster property(ies) labels`, so the
          docs now call this out instead of documenting label update as supported.\n\n##
          Why profiles instead of arbitrary kubelet config labels?\n\nProfiles avoid
          turning Magnum labels into a large untyped config transport. Operators own
          the reusable kubelet policy in the management cluster, while users get a
          small and validated label surface for selecting a profile and overriding
          the fields mcapi intentionally supports.\n\nThis also avoids hardcoding
          deployment-specific profiles in mcapi config. The source of truth is a normal
          Kubernetes resource in the management cluster, so operators can update profile
          definitions without changing mcapi code or oslo configuration.\n\n## Tests\n\nLocal
          validation:\n\n```bash\nuv run --python 3.10 pytest magnum_cluster_api/tests/unit/test_utils.py::TestKubeletConfigLabels
          magnum_cluster_api/tests/unit/test_utils.py::TestFillMissingLabelsFromTemplate
          magnum_cluster_api/tests/unit/test_resources.py magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_create_cluster
          magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_update_cluster_applies_topology_changes
          magnum_cluster_api/tests/unit/test_driver.py::TestDriver::test_update_cluster_merges_sparse_labels\ncargo
          test kubelet_config\ncargo test test_convert_values_to_cluster_topology_variables\nuvx
          pre-commit run --all-files\nuvx --with mkdocs-material --with mkdocs-literate-nav
          mkdocs build --strict\ngit diff --check HEAD\nrustfmt --check src/features/kubelet_config.rs\nuv
          run --python 3.10 python -m compileall -q magnum_cluster_api\n```\n\nResults:
          all passed.\n\nAIO OVN validation on `38.108.68.110`:\n\n- Rolled Magnum
          API, conductor, and `magnum-cluster-api-proxy` to a temporary local image
          built from this PR commit.\n- Created `ConfigMap/mcapi-kubelet-config-profiles`
          in `magnum-system` with `profile-gpu`.\n- Created a test cluster with `kubelet_config_profile=profile-gpu`
          plus explicit `kubelet_*` labels.\n- Confirmed the profile code loaded in
          the conductor and the ClusterClass rendered the `kubeletConfig` patch and
          schema.\n- Found and fixed the sparse-label live-path issue where user `--labels`
          replaced template labels and left the Rust driver without `kube_tag`.\n-
          Re-tested Magnum label update: a no-op replace of the existing `kubelet_config_profile=profile-gpu`
          was accepted, but changing `labels/kubelet_max_pods=240` was rejected by
          Magnum API with HTTP 400 `cannot change cluster property(ies) labels`; docs
          were updated to state kubelet labels are create-time settings.\n- Full CAPI
          Cluster creation is currently blocked by existing AIO OpenStackSDK compatibility
          issues outside this PR path, first in Magnum API validation and then in
          conductor helper calls such as `osc.cinder().volume_types`.\n- Restored
          Magnum API, conductor, and `magnum-cluster-api-proxy` to `ghcr.io/vexxhost/magnum:main@sha256:be30fc62b97ee15502c211cc1c73ae698a47d9ea7d5982a396db1d677f2088aa`
          after testing."
        change_url: https://github.com/vexxhost/magnum-cluster-api/pull/1013
        commit_id: 4293b702fdcd4e96f2c1b94dc295d6e7622dace2
        patchset: 4293b702fdcd4e96f2c1b94dc295d6e7622dace2
        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.34.7-calico
      jobtags: []
      max_attempts: 3
      message: ZmVhdDogY29uZmlndXJlIGt1YmVsZXQgdmlhIGt1YmVhZG0gY29uZmlnIHBhdGNoZXMKCiMjIFByb2JsZW0KCkJhcmVtZXRhbCBhbmQgR1BVLW9yaWVudGVkIEt1YmVybmV0ZXMgY2x1c3RlcnMgbmVlZCBrdWJlbGV0IENQVSwgdG9wb2xvZ3ksIGFuZCBwb2QtZGVuc2l0eSB0dW5pbmcgdGhyb3VnaCBNYWdudW0gbGFiZWxzIHNvIHRoZSBzZXR0aW5ncyBzdXJ2aXZlIG5vZGUgcmVwbGFjZW1lbnQsIHNjYWxlLXVwLCBhbmQgcm9sbGluZyB1cGdyYWRlcy4gVGhlIG9sZCBhbHRlcm5hdGl2ZXMgYXJlIHdlYWsgZm9yIHByb2R1Y3Rpb246CgotIHBvc3QtY3JlYXRlIFNTSCBlZGl0cyB0byBgL3Zhci9saWIva3ViZWxldC9jb25maWcueWFtbGAgYXJlIG5vdCBkZWNsYXJhdGl2ZSBhbmQgZG8gbm90IHN1cnZpdmUgcmVwbGFjZW1lbnQ7Ci0gYGt1YmVsZXRFeHRyYUFyZ3NgIGZvcndhcmRzIGNvbW1hbmQtbGluZSBmbGFncywgYnV0IGt1YmVsZXQgaXMgbW92aW5nIHRoZXNlIHNldHRpbmdzIHRvIHN0cnVjdHVyZWQgY29uZmlndXJhdGlvbiBhbmQgdGhlIGVxdWl2YWxlbnQgQ0xJIGZsYWdzIGFyZSBkZXByZWNhdGVkOwotIGFjY2VwdGluZyBhcmJpdHJhcnkgSlNPTi9ZQU1MIGZyb20gYSBNYWdudW0gbGFiZWwgd291bGQgbWFrZSBsYWJlbHMgY2FycnkgdG9vIG11Y2ggc3RydWN0dXJlZCBjb25maWd1cmF0aW9uIGFuZCB3b3VsZCBiZSBoYXJkIHRvIHZhbGlkYXRlIHNhZmVseS4KCiMjIFNvbHV0aW9uCgpQUiAjMTAxMyBleHBvc2VzIGEgc3RydWN0dXJlZCBrdWJlbGV0IGNvbmZpZ3VyYXRpb24gcGF0aCBiYWNrZWQgYnkgb3BlcmF0b3ItbWFuYWdlZCBwcm9maWxlcy4KCk9wZXJhdG9ycyBkZWZpbmUgcmV1c2FibGUga3ViZWxldCBwcm9maWxlcyBpbiB0aGUgbWFuYWdlbWVudCBLdWJlcm5ldGVzIGNsdXN0ZXIgd2l0aCB0aGlzIENvbmZpZ01hcDoKCmBgYHlhbWwKYXBpVmVyc2lvbjogdjEKa2luZDogQ29uZmlnTWFwCm1ldGFkYXRhOgogIG5hbWU6IG1jYXBpLWt1YmVsZXQtY29uZmlnLXByb2ZpbGVzCiAgbmFtZXNwYWNlOiBtYWdudW0tc3lzdGVtCmRhdGE6CiAgcHJvZmlsZS1ncHU6IHwKICAgIGNwdU1hbmFnZXJQb2xpY3k6IHN0YXRpYwogICAgdG9wb2xvZ3lNYW5hZ2VyUG9saWN5OiBzaW5nbGUtbnVtYS1ub2RlCiAgICByZXNlcnZlZFN5c3RlbUNQVXM6IDAtMQogICAgbWF4UG9kczogMjUwCmBgYAoKVXNlcnMgc2VsZWN0IGEgcHJlZGVmaW5lZCBwcm9maWxlIHdpdGggYGt1YmVsZXRfY29uZmlnX3Byb2ZpbGU9PG5hbWU+YCwgdGhlbiBtYXkgb3ZlcnJpZGUgaW5kaXZpZHVhbCBzdXBwb3J0ZWQgZmllbGRzIHdpdGggdHlwZWQgbGFiZWxzIGF0IGNsdXN0ZXIgY3JlYXRpb24gdGltZToKCnwgTGFiZWwgfCBFeGFtcGxlIHwgRWZmZWN0IHwKfC0tLXwtLS18LS0tfAp8IGBrdWJlbGV0X2NvbmZpZ19wcm9maWxlYCB8IGBwcm9maWxlLWdwdWAgfCBMb2FkcyBvcGVyYXRvci1kZWZpbmVkIGRlZmF1bHRzIGZyb20gYENvbmZpZ01hcC9tY2FwaS1rdWJlbGV0LWNvbmZpZy1wcm9maWxlc2AuIHwKfCBga3ViZWxldF9tYXhfcG9kc2AgfCBgMjUwYCB8IFNldHMga3ViZWxldCBgbWF4UG9kc2AuIHwKfCBga3ViZWxldF9jcHVfbWFuYWdlcl9wb2xpY3lgIHwgYHN0YXRpY2AgfCBTZXRzIGt1YmVsZXQgYGNwdU1hbmFnZXJQb2xpY3lgLiBBY2NlcHRlZCB2YWx1ZXM6IGBub25lYCwgYHN0YXRpY2AuIHwKfCBga3ViZWxldF90b3BvbG9neV9tYW5hZ2VyX3BvbGljeWAgfCBgc2luZ2xlLW51bWEtbm9kZWAgfCBTZXRzIGt1YmVsZXQgYHRvcG9sb2d5TWFuYWdlclBvbGljeWAuIEFjY2VwdGVkIHZhbHVlczogYG5vbmVgLCBgYmVzdC1lZmZvcnRgLCBgcmVzdHJpY3RlZGAsIGBzaW5nbGUtbnVtYS1ub2RlYC4gfAp8IGBrdWJlbGV0X3Jlc2VydmVkX2NwdXNgIHwgYDAtMWAgfCBTZXRzIGt1YmVsZXQgYHJlc2VydmVkU3lzdGVtQ1BVc2AuIHwKCkV4cGxpY2l0IGxhYmVscyB3aW4gb3ZlciBwcm9maWxlIGRlZmF1bHRzLgoKV2hlbiBhIHByb2ZpbGUgb3IgYW55IGt1YmVsZXQgbGFiZWwgaXMgc2V0LCBtY2FwaSBwYXNzZXMgYSBga3ViZWxldENvbmZpZ2AgQ2x1c3RlckNsYXNzIHRvcG9sb2d5IHZhcmlhYmxlIGFuZCByZW5kZXJzIGAvZXRjL2t1YmVybmV0ZXMvcGF0Y2hlcy9rdWJlbGV0Y29uZmlndXJhdGlvbittZXJnZS55YW1sYCBpbnRvIGJvdGggY29udHJvbC1wbGFuZSBhbmQgd29ya2VyIGt1YmVhZG0gY29uZmlncy4gVGhlIGZlYXR1cmUgYWxzbyBzZXRzIHRoZSBrdWJlYWRtIHBhdGNoZXMgZGlyZWN0b3J5IHRvIGAvZXRjL2t1YmVybmV0ZXMvcGF0Y2hlc2AgZm9yIGluaXQvam9pbiBwYXRocy4KCm1jYXBpIHZhbGlkYXRlcyB0aGUgcmVxdWVzdGVkIHByb2ZpbGUgYmVmb3JlIGNyZWF0aW5nIHRoZSBjbHVzdGVyLiBJZiB0aGUgQ29uZmlnTWFwIGlzIG1pc3NpbmcsIHRoZSBwcm9maWxlIG5hbWUgaXMgdW5rbm93biwgdGhlIHByb2ZpbGUgWUFNTCBpcyBpbnZhbGlkLCBvciB0aGUgcHJvZmlsZSBjb250YWlucyB1bnN1cHBvcnRlZC9pbnZhbGlkIGZpZWxkcywgY2x1c3RlciBjcmVhdGlvbiBmYWlscyBiZWZvcmUgQ0FQSSByZXNvdXJjZXMgYXJlIHJlbmRlcmVkLgoKVGhlIGRyaXZlciBhbHNvIG1lcmdlcyBhbnkgbWlzc2luZyBjbHVzdGVyLXRlbXBsYXRlIGxhYmVscyBpbnRvIHRoZSBzcGFyc2UgYGNsdXN0ZXIubGFiZWxzYCB2YWx1ZSB0aGF0IE1hZ251bSBzdG9yZXMgd2hlbiB1c2VycyBwYXNzIGAtLWxhYmVsc2AsIHNvIHJlcXVpcmVkIHRlbXBsYXRlIGxhYmVscyBzdWNoIGFzIGBrdWJlX3RhZ2AgcmVtYWluIGF2YWlsYWJsZSB0byB0aGUgUnVzdCBkcml2ZXIgYW5kIGxhdGVyIG1vbml0b3IvZGVsZXRlIHBhdGhzLgoKIyMgVXNhZ2UKCmBgYGJhc2gKb3BlbnN0YWNrIGNvZSBjbHVzdGVyIGNyZWF0ZSBibS1ncHUgXAogIC0tY2x1c3Rlci10ZW1wbGF0ZSBrOHMtYm0gXAogIC0tbGFiZWxzIGt1YmVsZXRfbWF4X3BvZHM9MjUwIFwKICAtLWxhYmVscyBrdWJlbGV0X2NwdV9tYW5hZ2VyX3BvbGljeT1zdGF0aWMgXAogIC0tbGFiZWxzIGt1YmVsZXRfdG9wb2xvZ3lfbWFuYWdlcl9wb2xpY3k9c2luZ2xlLW51bWEtbm9kZSBcCiAgLS1sYWJlbHMga3ViZWxldF9yZXNlcnZlZF9jcHVzPTAtMSBcCiAgLS1sYWJlbHMga3ViZWxldF9jb25maWdfcHJvZmlsZT1wcm9maWxlLWdwdQpgYGAKClRvIHZlcmlmeSByZW5kZXJpbmcgYmVmb3JlIG5vZGVzIGFyZSBSZWFkeSwgaW5zcGVjdCB0aGUgZ2VuZXJhdGVkIENBUEkvYm9vdHN0cmFwIHJlc291cmNlcyBmb3I6CgpgYGB5YW1sCnBhdGg6IC9ldGMva3ViZXJuZXRlcy9wYXRjaGVzL2t1YmVsZXRjb25maWd1cmF0aW9uK21lcmdlLnlhbWwKY29udGVudDogfAogIGFwaVZlcnNpb246IGt1YmVsZXQuY29uZmlnLms4cy5pby92MWJldGExCiAga2luZDogS3ViZWxldENvbmZpZ3VyYXRpb24KICBjcHVNYW5hZ2VyUG9saWN5OiBzdGF0aWMKICB0b3BvbG9neU1hbmFnZXJQb2xpY3k6IHNpbmdsZS1udW1hLW5vZGUKICByZXNlcnZlZFN5c3RlbUNQVXM6IDAtMQogIG1heFBvZHM6IDI1MApgYGAKCk9uY2Ugbm9kZXMgYXJlIFJlYWR5LCB2ZXJpZnkgdGhlIG1lcmdlZCBrdWJlbGV0IGNvbmZpZyBvbiBhIG5vZGU6CgpgYGBiYXNoCnN1ZG8gZ3JlcCAtRSAnY3B1TWFuYWdlclBvbGljeXx0b3BvbG9neU1hbmFnZXJQb2xpY3l8cmVzZXJ2ZWRTeXN0ZW1DUFVzfG1heFBvZHMnIC92YXIvbGliL2t1YmVsZXQvY29uZmlnLnlhbWwKYGBgCgpLdWJlbGV0IHByb2ZpbGUgbGFiZWxzIGFyZSBzZWxlY3RlZCB3aGVuIHRoZSBjbHVzdGVyIGlzIGNyZWF0ZWQuIEkgdGVzdGVkIGBvcGVuc3RhY2sgY29lIGNsdXN0ZXIgdXBkYXRlIC4uLiByZXBsYWNlIGxhYmVscy9rdWJlbGV0X21heF9wb2RzPTI0MGAgb24gdGhlIEFJTyBhbmQgTWFnbnVtIHJlamVjdHMgcmVhbCBsYWJlbCBjaGFuZ2VzIHdpdGggYGNhbm5vdCBjaGFuZ2UgY2x1c3RlciBwcm9wZXJ0eShpZXMpIGxhYmVsc2AsIHNvIHRoZSBkb2NzIG5vdyBjYWxsIHRoaXMgb3V0IGluc3RlYWQgb2YgZG9jdW1lbnRpbmcgbGFiZWwgdXBkYXRlIGFzIHN1cHBvcnRlZC4KCiMjIFdoeSBwcm9maWxlcyBpbnN0ZWFkIG9mIGFyYml0cmFyeSBrdWJlbGV0IGNvbmZpZyBsYWJlbHM/CgpQcm9maWxlcyBhdm9pZCB0dXJuaW5nIE1hZ251bSBsYWJlbHMgaW50byBhIGxhcmdlIHVudHlwZWQgY29uZmlnIHRyYW5zcG9ydC4gT3BlcmF0b3JzIG93biB0aGUgcmV1c2FibGUga3ViZWxldCBwb2xpY3kgaW4gdGhlIG1hbmFnZW1lbnQgY2x1c3Rlciwgd2hpbGUgdXNlcnMgZ2V0IGEgc21hbGwgYW5kIHZhbGlkYXRlZCBsYWJlbCBzdXJmYWNlIGZvciBzZWxlY3RpbmcgYSBwcm9maWxlIGFuZCBvdmVycmlkaW5nIHRoZSBmaWVsZHMgbWNhcGkgaW50ZW50aW9uYWxseSBzdXBwb3J0cy4KClRoaXMgYWxzbyBhdm9pZHMgaGFyZGNvZGluZyBkZXBsb3ltZW50LXNwZWNpZmljIHByb2ZpbGVzIGluIG1jYXBpIGNvbmZpZy4gVGhlIHNvdXJjZSBvZiB0cnV0aCBpcyBhIG5vcm1hbCBLdWJlcm5ldGVzIHJlc291cmNlIGluIHRoZSBtYW5hZ2VtZW50IGNsdXN0ZXIsIHNvIG9wZXJhdG9ycyBjYW4gdXBkYXRlIHByb2ZpbGUgZGVmaW5pdGlvbnMgd2l0aG91dCBjaGFuZ2luZyBtY2FwaSBjb2RlIG9yIG9zbG8gY29uZmlndXJhdGlvbi4KCiMjIFRlc3RzCgpMb2NhbCB2YWxpZGF0aW9uOgoKYGBgYmFzaAp1diBydW4gLS1weXRob24gMy4xMCBweXRlc3QgbWFnbnVtX2NsdXN0ZXJfYXBpL3Rlc3RzL3VuaXQvdGVzdF91dGlscy5weTo6VGVzdEt1YmVsZXRDb25maWdMYWJlbHMgbWFnbnVtX2NsdXN0ZXJfYXBpL3Rlc3RzL3VuaXQvdGVzdF91dGlscy5weTo6VGVzdEZpbGxNaXNzaW5nTGFiZWxzRnJvbVRlbXBsYXRlIG1hZ251bV9jbHVzdGVyX2FwaS90ZXN0cy91bml0L3Rlc3RfcmVzb3VyY2VzLnB5IG1hZ251bV9jbHVzdGVyX2FwaS90ZXN0cy91bml0L3Rlc3RfZHJpdmVyLnB5OjpUZXN0RHJpdmVyOjp0ZXN0X2NyZWF0ZV9jbHVzdGVyIG1hZ251bV9jbHVzdGVyX2FwaS90ZXN0cy91bml0L3Rlc3RfZHJpdmVyLnB5OjpUZXN0RHJpdmVyOjp0ZXN0X3VwZGF0ZV9jbHVzdGVyX2FwcGxpZXNfdG9wb2xvZ3lfY2hhbmdlcyBtYWdudW1fY2x1c3Rlcl9hcGkvdGVzdHMvdW5pdC90ZXN0X2RyaXZlci5weTo6VGVzdERyaXZlcjo6dGVzdF91cGRhdGVfY2x1c3Rlcl9tZXJnZXNfc3BhcnNlX2xhYmVscwpjYXJnbyB0ZXN0IGt1YmVsZXRfY29uZmlnCmNhcmdvIHRlc3QgdGVzdF9jb252ZXJ0X3ZhbHVlc190b19jbHVzdGVyX3RvcG9sb2d5X3ZhcmlhYmxlcwp1dnggcHJlLWNvbW1pdCBydW4gLS1hbGwtZmlsZXMKdXZ4IC0td2l0aCBta2RvY3MtbWF0ZXJpYWwgLS13aXRoIG1rZG9jcy1saXRlcmF0ZS1uYXYgbWtkb2NzIGJ1aWxkIC0tc3RyaWN0CmdpdCBkaWZmIC0tY2hlY2sgSEVBRApydXN0Zm10IC0tY2hlY2sgc3JjL2ZlYXR1cmVzL2t1YmVsZXRfY29uZmlnLnJzCnV2IHJ1biAtLXB5dGhvbiAzLjEwIHB5dGhvbiAtbSBjb21waWxlYWxsIC1xIG1hZ251bV9jbHVzdGVyX2FwaQpgYGAKClJlc3VsdHM6IGFsbCBwYXNzZWQuCgpBSU8gT1ZOIHZhbGlkYXRpb24gb24gYDM4LjEwOC42OC4xMTBgOgoKLSBSb2xsZWQgTWFnbnVtIEFQSSwgY29uZHVjdG9yLCBhbmQgYG1hZ251bS1jbHVzdGVyLWFwaS1wcm94eWAgdG8gYSB0ZW1wb3JhcnkgbG9jYWwgaW1hZ2UgYnVpbHQgZnJvbSB0aGlzIFBSIGNvbW1pdC4KLSBDcmVhdGVkIGBDb25maWdNYXAvbWNhcGkta3ViZWxldC1jb25maWctcHJvZmlsZXNgIGluIGBtYWdudW0tc3lzdGVtYCB3aXRoIGBwcm9maWxlLWdwdWAuCi0gQ3JlYXRlZCBhIHRlc3QgY2x1c3RlciB3aXRoIGBrdWJlbGV0X2NvbmZpZ19wcm9maWxlPXByb2ZpbGUtZ3B1YCBwbHVzIGV4cGxpY2l0IGBrdWJlbGV0XypgIGxhYmVscy4KLSBDb25maXJtZWQgdGhlIHByb2ZpbGUgY29kZSBsb2FkZWQgaW4gdGhlIGNvbmR1Y3RvciBhbmQgdGhlIENsdXN0ZXJDbGFzcyByZW5kZXJlZCB0aGUgYGt1YmVsZXRDb25maWdgIHBhdGNoIGFuZCBzY2hlbWEuCi0gRm91bmQgYW5kIGZpeGVkIHRoZSBzcGFyc2UtbGFiZWwgbGl2ZS1wYXRoIGlzc3VlIHdoZXJlIHVzZXIgYC0tbGFiZWxzYCByZXBsYWNlZCB0ZW1wbGF0ZSBsYWJlbHMgYW5kIGxlZnQgdGhlIFJ1c3QgZHJpdmVyIHdpdGhvdXQgYGt1YmVfdGFnYC4KLSBSZS10ZXN0ZWQgTWFnbnVtIGxhYmVsIHVwZGF0ZTogYSBuby1vcCByZXBsYWNlIG9mIHRoZSBleGlzdGluZyBga3ViZWxldF9jb25maWdfcHJvZmlsZT1wcm9maWxlLWdwdWAgd2FzIGFjY2VwdGVkLCBidXQgY2hhbmdpbmcgYGxhYmVscy9rdWJlbGV0X21heF9wb2RzPTI0MGAgd2FzIHJlamVjdGVkIGJ5IE1hZ251bSBBUEkgd2l0aCBIVFRQIDQwMCBgY2Fubm90IGNoYW5nZSBjbHVzdGVyIHByb3BlcnR5KGllcykgbGFiZWxzYDsgZG9jcyB3ZXJlIHVwZGF0ZWQgdG8gc3RhdGUga3ViZWxldCBsYWJlbHMgYXJlIGNyZWF0ZS10aW1lIHNldHRpbmdzLgotIEZ1bGwgQ0FQSSBDbHVzdGVyIGNyZWF0aW9uIGlzIGN1cnJlbnRseSBibG9ja2VkIGJ5IGV4aXN0aW5nIEFJTyBPcGVuU3RhY2tTREsgY29tcGF0aWJpbGl0eSBpc3N1ZXMgb3V0c2lkZSB0aGlzIFBSIHBhdGgsIGZpcnN0IGluIE1hZ251bSBBUEkgdmFsaWRhdGlvbiBhbmQgdGhlbiBpbiBjb25kdWN0b3IgaGVscGVyIGNhbGxzIHN1Y2ggYXMgYG9zYy5jaW5kZXIoKS52b2x1bWVfdHlwZXNgLgotIFJlc3RvcmVkIE1hZ251bSBBUEksIGNvbmR1Y3RvciwgYW5kIGBtYWdudW0tY2x1c3Rlci1hcGktcHJveHlgIHRvIGBnaGNyLmlvL3ZleHhob3N0L21hZ251bTptYWluQHNoYTI1NjpiZTMwZmM2MmI5N2VlMTU1MDJjMjExY2MxYzczYWU2OThhNDdkOWVhN2Q1OTgyYTM5NmRiMWQ2NzdmMjA4OGFhYCBhZnRlciB0ZXN0aW5nLg==
      override_checkout: master
      patchset: 4293b702fdcd4e96f2c1b94dc295d6e7622dace2
      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: 79fe3eb1d01f8ac5739b0b7bc4759c407b6e248d
          trusted/project_2/github.com/vexxhost/zuul-jobs:
            canonical_name: github.com/vexxhost/zuul-jobs
            checkout: main
            commit: 348c7ff425450b0356e1d84589143dce260be74a
          untrusted/project_0/opendev.org/openstack/devstack:
            canonical_name: opendev.org/openstack/devstack
            checkout: master
            commit: bdfe1d9ac44cfa26e74db40bfbac03bafc45c98c
          untrusted/project_1/opendev.org/openstack/openstack-zuul-jobs:
            canonical_name: opendev.org/openstack/openstack-zuul-jobs
            checkout: master
            commit: 6d8b23c521afa615fab81e2777cd95218c9837d3
          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: 79fe3eb1d01f8ac5739b0b7bc4759c407b6e248d
          untrusted/project_4/github.com/vexxhost/zuul-jobs:
            canonical_name: github.com/vexxhost/zuul-jobs
            checkout: main
            commit: 348c7ff425450b0356e1d84589143dce260be74a
          untrusted/project_5/github.com/vexxhost/magnum-cluster-api:
            canonical_name: github.com/vexxhost/magnum-cluster-api
            checkout: main
            commit: d7f1c62c095d8e813d7fa90bc554325bb904e67e
        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: d7f1c62c095d8e813d7fa90bc554325bb904e67e
          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: 2d1ea8606784cb7e1147e869a79f6be7e8466236
          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: 7f6a196c65cbf3cc4952a9e80c1a1965c6699aad
          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: bdfe1d9ac44cfa26e74db40bfbac03bafc45c98c
          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: eac2fa47f26da3515c7a1e8c91226750517c52d4
          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: 2230026f77a8ed50493d2d58be9120910ceb2089
          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: efdfdc9ac1288918675cd2fac3ebc56c117adc64
          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: 2a78e94a652ddd7e2b666d74967f49122dfe4ba8
          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: 30374afe1ee08f3f6d3d7507310a6ffd3551e215
          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: f03e09d0a6eb0e3d4085c2448c302b9a5dda74fe
          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: d16fa5e723701c95cf97a3e9ea57b3856e09aaa7
          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: d0a7783cd02566847600d5db1c330e6865594331
          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: d2727844011a8f144c818556ed7e8d43f756576f
          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: b80aea157f95e9fa6ed14a2d44f9d0cf6ff9332d
          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: f8a07e962c7b0b2f1839761042d3a35ae3c51c43
          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: 0d356332512bb576b7813860f0df69304161a5b7
          name: openstack/swift
          required: true
          short_name: swift
          src_dir: src/opendev.org/openstack/swift
      ref: refs/pull/1013/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
