all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    debian-bookworm:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fe8f:2ea
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: a692f37f-e2b7-4e18-9542-62c3ebcbf5ff
        host_id: ec4f54fa666de9bc553bc59c41683f12345b665d0b1af00d715e7318
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fe8f:2ea
        label: debian-bookworm
        node_properties: {}
        private_ipv4: 10.128.7.70
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.193.25
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fe8f:2ea
        region: null
        slot: null
  vars:
    zuul:
      _inheritance_path:
      - '<Job base explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-config/zuul.d/jobs.yaml@main#2>'
      - '<Job python-osism-integration-tests explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/python-osism/.zuul.yaml@main#138>'
      - '<Job python-osism-integration-tests explicit: None implied: None source:
        osism/python-osism/.zuul.yaml@main#143>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: 0e034c1669cc43769f2b08d379d15031
      build_refs:
      - branch: main
        change: '2427'
        change_message: "Create per-device ZTP firmware symlink from sonic_parameters.version\n\n##
          Summary\n\nAdds support for per-device SONiC firmware selection to the `sync
          sonic` command, matching the ZTP `dynamic-url` switch in [osism/ansible-collection-services#2131](https://github.com/osism/ansible-collection-services/pull/2131).\n\nThat
          PR changed the ZTP firmware install to a `dynamic-url` built from `<prefix><identifier><suffix>`
          (identifier `serial-number`), so each switch fetches `sonic-broadcom-enterprise-base_<serial>.bin`
          during ZTP. For that name to resolve to the right image, a per-serial link
          to the version-specific image must exist. The serial\u2192version mapping
          lives in NetBox (`sonic_parameters.version`), and `sync sonic` already writes
          the per-serial artefacts into the export directory.\n\n## Changes\n\n- **Settings**
          (`settings.py`): new `SONIC_FIRMWARE_DIR` / `_PREFIX` / `_SUFFIX` / `_IDENTIFIER`,
          mirroring the ansible httpd role defaults. `SONIC_FIRMWARE_DIR` defaults
          to the same httpd-served directory as the config exports (`/etc/sonic/export`).\n-
          **`export_firmware_link()`** (`exporter.py`): creates `<prefix><serial><suffix>`
          as a *relative* symlink to `<prefix><version><suffix>`. Reconciled on every
          run (missing/stale/wrongly-pointed links are repaired), skips devices without
          a configured version, and raises on real failures so they surface as a non-zero
          task rc. The target image is provided out of band (e.g. downloaded by metalbox),
          so a dangling link until it arrives is expected.\n- **`sync_sonic`** (`sync.py`):
          reads `sonic_parameters.version` per device (like `hwsku` / `config_version`)
          and passes it to the exporter. `config_db.json` and the CONFIG DB VERSION
          are untouched.\n\nFor the example device (serial `732656X2419308`, `version:
          4.4.2`) this produces:\n\n```\n/etc/sonic/export/sonic-broadcom-enterprise-base_732656X2419308.bin\n
          \   -> sonic-broadcom-enterprise-base_4.4.2.bin\n```\n\n## Tests\n\n- 13
          tests in `test_exporter.py` (identifier/target naming, serial fallback,
          reconciliation, self-reference guard, error paths).\n- 3 tests in `test_sync.py`
          (version \u2192 firmware link, `None` when absent, rc=1 on failure); `patch_sync_deps`
          and `make_device` extended accordingly.\n\n\U0001F916 Generated with [Claude
          Code](https://claude.com/claude-code)"
        change_url: https://github.com/osism/python-osism/pull/2427
        commit_id: b06ca1af5faab191146ca8fa0bbc8c444c564224
        patchset: b06ca1af5faab191146ca8fa0bbc8c444c564224
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          name: osism/python-osism
          short_name: python-osism
        src_dir: src/github.com/osism/python-osism
        topic: null
      buildset: 8738d993cec84479b5d8df0d94863433
      buildset_refs:
      - branch: main
        change: '2427'
        change_message: "Create per-device ZTP firmware symlink from sonic_parameters.version\n\n##
          Summary\n\nAdds support for per-device SONiC firmware selection to the `sync
          sonic` command, matching the ZTP `dynamic-url` switch in [osism/ansible-collection-services#2131](https://github.com/osism/ansible-collection-services/pull/2131).\n\nThat
          PR changed the ZTP firmware install to a `dynamic-url` built from `<prefix><identifier><suffix>`
          (identifier `serial-number`), so each switch fetches `sonic-broadcom-enterprise-base_<serial>.bin`
          during ZTP. For that name to resolve to the right image, a per-serial link
          to the version-specific image must exist. The serial\u2192version mapping
          lives in NetBox (`sonic_parameters.version`), and `sync sonic` already writes
          the per-serial artefacts into the export directory.\n\n## Changes\n\n- **Settings**
          (`settings.py`): new `SONIC_FIRMWARE_DIR` / `_PREFIX` / `_SUFFIX` / `_IDENTIFIER`,
          mirroring the ansible httpd role defaults. `SONIC_FIRMWARE_DIR` defaults
          to the same httpd-served directory as the config exports (`/etc/sonic/export`).\n-
          **`export_firmware_link()`** (`exporter.py`): creates `<prefix><serial><suffix>`
          as a *relative* symlink to `<prefix><version><suffix>`. Reconciled on every
          run (missing/stale/wrongly-pointed links are repaired), skips devices without
          a configured version, and raises on real failures so they surface as a non-zero
          task rc. The target image is provided out of band (e.g. downloaded by metalbox),
          so a dangling link until it arrives is expected.\n- **`sync_sonic`** (`sync.py`):
          reads `sonic_parameters.version` per device (like `hwsku` / `config_version`)
          and passes it to the exporter. `config_db.json` and the CONFIG DB VERSION
          are untouched.\n\nFor the example device (serial `732656X2419308`, `version:
          4.4.2`) this produces:\n\n```\n/etc/sonic/export/sonic-broadcom-enterprise-base_732656X2419308.bin\n
          \   -> sonic-broadcom-enterprise-base_4.4.2.bin\n```\n\n## Tests\n\n- 13
          tests in `test_exporter.py` (identifier/target naming, serial fallback,
          reconciliation, self-reference guard, error paths).\n- 3 tests in `test_sync.py`
          (version \u2192 firmware link, `None` when absent, rc=1 on failure); `patch_sync_deps`
          and `make_device` extended accordingly.\n\n\U0001F916 Generated with [Claude
          Code](https://claude.com/claude-code)"
        change_url: https://github.com/osism/python-osism/pull/2427
        commit_id: b06ca1af5faab191146ca8fa0bbc8c444c564224
        patchset: b06ca1af5faab191146ca8fa0bbc8c444c564224
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          name: osism/python-osism
          short_name: python-osism
        src_dir: src/github.com/osism/python-osism
        topic: null
      change: '2427'
      change_message: "Create per-device ZTP firmware symlink from sonic_parameters.version\n\n##
        Summary\n\nAdds support for per-device SONiC firmware selection to the `sync
        sonic` command, matching the ZTP `dynamic-url` switch in [osism/ansible-collection-services#2131](https://github.com/osism/ansible-collection-services/pull/2131).\n\nThat
        PR changed the ZTP firmware install to a `dynamic-url` built from `<prefix><identifier><suffix>`
        (identifier `serial-number`), so each switch fetches `sonic-broadcom-enterprise-base_<serial>.bin`
        during ZTP. For that name to resolve to the right image, a per-serial link
        to the version-specific image must exist. The serial\u2192version mapping
        lives in NetBox (`sonic_parameters.version`), and `sync sonic` already writes
        the per-serial artefacts into the export directory.\n\n## Changes\n\n- **Settings**
        (`settings.py`): new `SONIC_FIRMWARE_DIR` / `_PREFIX` / `_SUFFIX` / `_IDENTIFIER`,
        mirroring the ansible httpd role defaults. `SONIC_FIRMWARE_DIR` defaults to
        the same httpd-served directory as the config exports (`/etc/sonic/export`).\n-
        **`export_firmware_link()`** (`exporter.py`): creates `<prefix><serial><suffix>`
        as a *relative* symlink to `<prefix><version><suffix>`. Reconciled on every
        run (missing/stale/wrongly-pointed links are repaired), skips devices without
        a configured version, and raises on real failures so they surface as a non-zero
        task rc. The target image is provided out of band (e.g. downloaded by metalbox),
        so a dangling link until it arrives is expected.\n- **`sync_sonic`** (`sync.py`):
        reads `sonic_parameters.version` per device (like `hwsku` / `config_version`)
        and passes it to the exporter. `config_db.json` and the CONFIG DB VERSION
        are untouched.\n\nFor the example device (serial `732656X2419308`, `version:
        4.4.2`) this produces:\n\n```\n/etc/sonic/export/sonic-broadcom-enterprise-base_732656X2419308.bin\n
        \   -> sonic-broadcom-enterprise-base_4.4.2.bin\n```\n\n## Tests\n\n- 13 tests
        in `test_exporter.py` (identifier/target naming, serial fallback, reconciliation,
        self-reference guard, error paths).\n- 3 tests in `test_sync.py` (version
        \u2192 firmware link, `None` when absent, rc=1 on failure); `patch_sync_deps`
        and `make_device` extended accordingly.\n\n\U0001F916 Generated with [Claude
        Code](https://claude.com/claude-code)"
      change_url: https://github.com/osism/python-osism/pull/2427
      child_jobs: []
      commit_id: b06ca1af5faab191146ca8fa0bbc8c444c564224
      event_id: 9986d3f0-7ab7-11f1-9e6b-27dae7ce8a80
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/0e034c1669cc43769f2b08d379d15031/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/0e034c1669cc43769f2b08d379d15031/work/logs
        result_data_file: /var/lib/zuul/builds/0e034c1669cc43769f2b08d379d15031/work/results.json
        src_root: /var/lib/zuul/builds/0e034c1669cc43769f2b08d379d15031/work/src
        work_root: /var/lib/zuul/builds/0e034c1669cc43769f2b08d379d15031/work
      include_vars: []
      items:
      - branch: main
        change: '2427'
        change_message: "Create per-device ZTP firmware symlink from sonic_parameters.version\n\n##
          Summary\n\nAdds support for per-device SONiC firmware selection to the `sync
          sonic` command, matching the ZTP `dynamic-url` switch in [osism/ansible-collection-services#2131](https://github.com/osism/ansible-collection-services/pull/2131).\n\nThat
          PR changed the ZTP firmware install to a `dynamic-url` built from `<prefix><identifier><suffix>`
          (identifier `serial-number`), so each switch fetches `sonic-broadcom-enterprise-base_<serial>.bin`
          during ZTP. For that name to resolve to the right image, a per-serial link
          to the version-specific image must exist. The serial\u2192version mapping
          lives in NetBox (`sonic_parameters.version`), and `sync sonic` already writes
          the per-serial artefacts into the export directory.\n\n## Changes\n\n- **Settings**
          (`settings.py`): new `SONIC_FIRMWARE_DIR` / `_PREFIX` / `_SUFFIX` / `_IDENTIFIER`,
          mirroring the ansible httpd role defaults. `SONIC_FIRMWARE_DIR` defaults
          to the same httpd-served directory as the config exports (`/etc/sonic/export`).\n-
          **`export_firmware_link()`** (`exporter.py`): creates `<prefix><serial><suffix>`
          as a *relative* symlink to `<prefix><version><suffix>`. Reconciled on every
          run (missing/stale/wrongly-pointed links are repaired), skips devices without
          a configured version, and raises on real failures so they surface as a non-zero
          task rc. The target image is provided out of band (e.g. downloaded by metalbox),
          so a dangling link until it arrives is expected.\n- **`sync_sonic`** (`sync.py`):
          reads `sonic_parameters.version` per device (like `hwsku` / `config_version`)
          and passes it to the exporter. `config_db.json` and the CONFIG DB VERSION
          are untouched.\n\nFor the example device (serial `732656X2419308`, `version:
          4.4.2`) this produces:\n\n```\n/etc/sonic/export/sonic-broadcom-enterprise-base_732656X2419308.bin\n
          \   -> sonic-broadcom-enterprise-base_4.4.2.bin\n```\n\n## Tests\n\n- 13
          tests in `test_exporter.py` (identifier/target naming, serial fallback,
          reconciliation, self-reference guard, error paths).\n- 3 tests in `test_sync.py`
          (version \u2192 firmware link, `None` when absent, rc=1 on failure); `patch_sync_deps`
          and `make_device` extended accordingly.\n\n\U0001F916 Generated with [Claude
          Code](https://claude.com/claude-code)"
        change_url: https://github.com/osism/python-osism/pull/2427
        commit_id: b06ca1af5faab191146ca8fa0bbc8c444c564224
        patchset: b06ca1af5faab191146ca8fa0bbc8c444c564224
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          name: osism/python-osism
          short_name: python-osism
          src_dir: src/github.com/osism/python-osism
        topic: null
      job: python-osism-integration-tests
      jobtags: []
      max_attempts: 3
      message: Q3JlYXRlIHBlci1kZXZpY2UgWlRQIGZpcm13YXJlIHN5bWxpbmsgZnJvbSBzb25pY19wYXJhbWV0ZXJzLnZlcnNpb24KCiMjIFN1bW1hcnkKCkFkZHMgc3VwcG9ydCBmb3IgcGVyLWRldmljZSBTT05pQyBmaXJtd2FyZSBzZWxlY3Rpb24gdG8gdGhlIGBzeW5jIHNvbmljYCBjb21tYW5kLCBtYXRjaGluZyB0aGUgWlRQIGBkeW5hbWljLXVybGAgc3dpdGNoIGluIFtvc2lzbS9hbnNpYmxlLWNvbGxlY3Rpb24tc2VydmljZXMjMjEzMV0oaHR0cHM6Ly9naXRodWIuY29tL29zaXNtL2Fuc2libGUtY29sbGVjdGlvbi1zZXJ2aWNlcy9wdWxsLzIxMzEpLgoKVGhhdCBQUiBjaGFuZ2VkIHRoZSBaVFAgZmlybXdhcmUgaW5zdGFsbCB0byBhIGBkeW5hbWljLXVybGAgYnVpbHQgZnJvbSBgPHByZWZpeD48aWRlbnRpZmllcj48c3VmZml4PmAgKGlkZW50aWZpZXIgYHNlcmlhbC1udW1iZXJgKSwgc28gZWFjaCBzd2l0Y2ggZmV0Y2hlcyBgc29uaWMtYnJvYWRjb20tZW50ZXJwcmlzZS1iYXNlXzxzZXJpYWw+LmJpbmAgZHVyaW5nIFpUUC4gRm9yIHRoYXQgbmFtZSB0byByZXNvbHZlIHRvIHRoZSByaWdodCBpbWFnZSwgYSBwZXItc2VyaWFsIGxpbmsgdG8gdGhlIHZlcnNpb24tc3BlY2lmaWMgaW1hZ2UgbXVzdCBleGlzdC4gVGhlIHNlcmlhbOKGknZlcnNpb24gbWFwcGluZyBsaXZlcyBpbiBOZXRCb3ggKGBzb25pY19wYXJhbWV0ZXJzLnZlcnNpb25gKSwgYW5kIGBzeW5jIHNvbmljYCBhbHJlYWR5IHdyaXRlcyB0aGUgcGVyLXNlcmlhbCBhcnRlZmFjdHMgaW50byB0aGUgZXhwb3J0IGRpcmVjdG9yeS4KCiMjIENoYW5nZXMKCi0gKipTZXR0aW5ncyoqIChgc2V0dGluZ3MucHlgKTogbmV3IGBTT05JQ19GSVJNV0FSRV9ESVJgIC8gYF9QUkVGSVhgIC8gYF9TVUZGSVhgIC8gYF9JREVOVElGSUVSYCwgbWlycm9yaW5nIHRoZSBhbnNpYmxlIGh0dHBkIHJvbGUgZGVmYXVsdHMuIGBTT05JQ19GSVJNV0FSRV9ESVJgIGRlZmF1bHRzIHRvIHRoZSBzYW1lIGh0dHBkLXNlcnZlZCBkaXJlY3RvcnkgYXMgdGhlIGNvbmZpZyBleHBvcnRzIChgL2V0Yy9zb25pYy9leHBvcnRgKS4KLSAqKmBleHBvcnRfZmlybXdhcmVfbGluaygpYCoqIChgZXhwb3J0ZXIucHlgKTogY3JlYXRlcyBgPHByZWZpeD48c2VyaWFsPjxzdWZmaXg+YCBhcyBhICpyZWxhdGl2ZSogc3ltbGluayB0byBgPHByZWZpeD48dmVyc2lvbj48c3VmZml4PmAuIFJlY29uY2lsZWQgb24gZXZlcnkgcnVuIChtaXNzaW5nL3N0YWxlL3dyb25nbHktcG9pbnRlZCBsaW5rcyBhcmUgcmVwYWlyZWQpLCBza2lwcyBkZXZpY2VzIHdpdGhvdXQgYSBjb25maWd1cmVkIHZlcnNpb24sIGFuZCByYWlzZXMgb24gcmVhbCBmYWlsdXJlcyBzbyB0aGV5IHN1cmZhY2UgYXMgYSBub24temVybyB0YXNrIHJjLiBUaGUgdGFyZ2V0IGltYWdlIGlzIHByb3ZpZGVkIG91dCBvZiBiYW5kIChlLmcuIGRvd25sb2FkZWQgYnkgbWV0YWxib3gpLCBzbyBhIGRhbmdsaW5nIGxpbmsgdW50aWwgaXQgYXJyaXZlcyBpcyBleHBlY3RlZC4KLSAqKmBzeW5jX3NvbmljYCoqIChgc3luYy5weWApOiByZWFkcyBgc29uaWNfcGFyYW1ldGVycy52ZXJzaW9uYCBwZXIgZGV2aWNlIChsaWtlIGBod3NrdWAgLyBgY29uZmlnX3ZlcnNpb25gKSBhbmQgcGFzc2VzIGl0IHRvIHRoZSBleHBvcnRlci4gYGNvbmZpZ19kYi5qc29uYCBhbmQgdGhlIENPTkZJRyBEQiBWRVJTSU9OIGFyZSB1bnRvdWNoZWQuCgpGb3IgdGhlIGV4YW1wbGUgZGV2aWNlIChzZXJpYWwgYDczMjY1NlgyNDE5MzA4YCwgYHZlcnNpb246IDQuNC4yYCkgdGhpcyBwcm9kdWNlczoKCmBgYAovZXRjL3NvbmljL2V4cG9ydC9zb25pYy1icm9hZGNvbS1lbnRlcnByaXNlLWJhc2VfNzMyNjU2WDI0MTkzMDguYmluCiAgICAtPiBzb25pYy1icm9hZGNvbS1lbnRlcnByaXNlLWJhc2VfNC40LjIuYmluCmBgYAoKIyMgVGVzdHMKCi0gMTMgdGVzdHMgaW4gYHRlc3RfZXhwb3J0ZXIucHlgIChpZGVudGlmaWVyL3RhcmdldCBuYW1pbmcsIHNlcmlhbCBmYWxsYmFjaywgcmVjb25jaWxpYXRpb24sIHNlbGYtcmVmZXJlbmNlIGd1YXJkLCBlcnJvciBwYXRocykuCi0gMyB0ZXN0cyBpbiBgdGVzdF9zeW5jLnB5YCAodmVyc2lvbiDihpIgZmlybXdhcmUgbGluaywgYE5vbmVgIHdoZW4gYWJzZW50LCByYz0xIG9uIGZhaWx1cmUpOyBgcGF0Y2hfc3luY19kZXBzYCBhbmQgYG1ha2VfZGV2aWNlYCBleHRlbmRlZCBhY2NvcmRpbmdseS4KCvCfpJYgR2VuZXJhdGVkIHdpdGggW0NsYXVkZSBDb2RlXShodHRwczovL2NsYXVkZS5jb20vY2xhdWRlLWNvZGUp
      patchset: b06ca1af5faab191146ca8fa0bbc8c444c564224
      pipeline: check
      playbook_context:
        playbook_projects:
          trusted/project_0/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 71b711c422c10c242a8f785dc6d41ed9d12e9cd3
          trusted/project_1/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 242732586e2cba04d04867d3e302888c766bc231
          trusted/project_2/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: 1d71e58c93442038e695a5d883d57a603182c7ae
          untrusted/project_0/github.com/osism/python-osism:
            canonical_name: github.com/osism/python-osism
            checkout: main
            commit: 8b2f1594b0e378849f3a28dff1b609b05be786e1
          untrusted/project_1/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 71b711c422c10c242a8f785dc6d41ed9d12e9cd3
          untrusted/project_2/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 242732586e2cba04d04867d3e302888c766bc231
          untrusted/project_3/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: 1d71e58c93442038e695a5d883d57a603182c7ae
        playbooks:
        - path: untrusted/project_0/github.com/osism/python-osism/playbooks/test-integration.yml
          roles:
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/playbook_0/role_1/zuul-config
            link_target: untrusted/project_1/github.com/osism/zuul-config
            role_path: ansible/playbook_0/role_1/zuul-config/roles
          - checkout: master
            checkout_description: project default branch
            link_name: ansible/playbook_0/role_2/openinfra-zuul-jobs
            link_target: untrusted/project_2/github.com/osism/openinfra-zuul-jobs
            role_path: ansible/playbook_0/role_2/openinfra-zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/playbook_0/role_3/zuul-jobs
            link_target: untrusted/project_3/github.com/osism/zuul-jobs
            role_path: ansible/playbook_0/role_3/zuul-jobs/roles
      post_review: false
      post_timeout: 1800
      pre_timeout: null
      project:
        canonical_hostname: github.com
        canonical_name: github.com/osism/python-osism
        name: osism/python-osism
        short_name: python-osism
        src_dir: src/github.com/osism/python-osism
      projects:
        github.com/osism/python-osism:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          checkout: main
          checkout_description: zuul branch
          commit: 8b2f1594b0e378849f3a28dff1b609b05be786e1
          name: osism/python-osism
          required: false
          short_name: python-osism
          src_dir: src/github.com/osism/python-osism
      ref: refs/pull/2427/head
      resources: {}
      tenant: osism
      timeout: 1800
      topic: null
      voting: true
