├── .html
├── packages
├── jumpstarter-testing
│ ├── README.md
│ ├── jumpstarter_testing
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ └── pytest_test.py
│ ├── conftest.py
│ └── pyproject.toml
├── hatch-pin-jumpstarter
│ ├── README.md
│ ├── src
│ │ └── hatch_pin_jumpstarter
│ │ │ └── py.typed
│ └── pyproject.toml
├── jumpstarter-imagehash
│ ├── README.md
│ ├── jumpstarter_imagehash
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ ├── test_image_a.jpeg
│ │ └── test_image_b.jpeg
│ └── pyproject.toml
├── jumpstarter-protocol
│ ├── README.md
│ ├── jumpstarter_protocol
│ │ ├── py.typed
│ │ ├── jumpstarter
│ │ │ ├── __init__.py
│ │ │ ├── v1
│ │ │ │ ├── __init__.py
│ │ │ │ ├── common_pb2_grpc.py
│ │ │ │ └── kubernetes_pb2_grpc.py
│ │ │ └── client
│ │ │ │ ├── __init__.py
│ │ │ │ └── v1
│ │ │ │ └── __init__.py
│ │ └── __init__.py
│ ├── protocol_test.py
│ └── pyproject.toml
├── jumpstarter
│ ├── jumpstarter
│ │ ├── py.typed
│ │ ├── config
│ │ │ ├── __init__.py
│ │ │ ├── shell.py
│ │ │ ├── tls.py
│ │ │ ├── env.py
│ │ │ ├── common.py
│ │ │ └── grpc.py
│ │ ├── streams
│ │ │ ├── __init__.py
│ │ │ ├── blocking.py
│ │ │ ├── aiohttp.py
│ │ │ ├── encoding_test.py
│ │ │ └── metadata.py
│ │ ├── utils
│ │ │ └── __init__.py
│ │ ├── exporter
│ │ │ ├── __init__.py
│ │ │ └── logging.py
│ │ ├── driver
│ │ │ ├── __init__.py
│ │ │ ├── decorators_test.py
│ │ │ └── decorators.py
│ │ ├── client
│ │ │ ├── exceptions.py
│ │ │ ├── __init__.py
│ │ │ └── adapters.py
│ │ ├── common
│ │ │ ├── __init__.py
│ │ │ ├── metadata.py
│ │ │ ├── serde.py
│ │ │ ├── importlib_test.py
│ │ │ ├── utils_test.py
│ │ │ ├── resources.py
│ │ │ └── condition.py
│ │ └── __init__.py
│ └── README.md
├── jumpstarter-cli
│ ├── jumpstarter_cli
│ │ ├── py.typed
│ │ ├── __main__.py
│ │ ├── config.py
│ │ ├── __init__.py
│ │ ├── cli_test.py
│ │ ├── jmp.py
│ │ └── update.py
│ ├── README.md
│ └── pyproject.toml
├── jumpstarter-cli-admin
│ ├── README.md
│ ├── jumpstarter_cli_admin
│ │ ├── py.typed
│ │ ├── __main__.py
│ │ ├── test_utils.py
│ │ ├── k8s.py
│ │ └── __init__.py
│ └── pyproject.toml
├── jumpstarter-cli-common
│ ├── jumpstarter_cli_common
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ ├── blocking.py
│ │ └── signal.py
│ ├── README.md
│ └── pyproject.toml
├── jumpstarter-driver-can
│ ├── jumpstarter_driver_can
│ │ ├── py.typed
│ │ └── __init__.py
│ └── pyproject.toml
├── jumpstarter-kubernetes
│ ├── jumpstarter_kubernetes
│ │ ├── py.typed
│ │ ├── util
│ │ │ └── __init__.py
│ │ ├── list.py
│ │ ├── json.py
│ │ └── serialize.py
│ ├── README.md
│ └── pyproject.toml
├── jumpstarter-driver-ble
│ ├── jumpstarter_driver_ble
│ │ ├── __init__.py
│ │ └── driver_test.py
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-flashers
│ ├── oci_bundles
│ │ ├── rcar_s4
│ │ │ ├── data
│ │ │ │ └── .keep
│ │ │ ├── overlay
│ │ │ │ └── etc
│ │ │ │ │ ├── udev
│ │ │ │ │ └── rules.d
│ │ │ │ │ │ └── 10-rename-tsn0.rules
│ │ │ │ │ └── network
│ │ │ │ │ └── if-pre-up.d
│ │ │ │ │ └── wait-carrier.sh
│ │ │ ├── build_flasher.sh
│ │ │ ├── rootfs_only_defconfig
│ │ │ └── manifest.yaml
│ │ ├── aarch64-itb
│ │ │ ├── data
│ │ │ │ └── .gitkeep
│ │ │ ├── manifest.yaml
│ │ │ ├── overlay
│ │ │ │ └── etc
│ │ │ │ │ ├── udev
│ │ │ │ │ └── rules.d
│ │ │ │ │ │ └── 10-rename-tsn0.rules
│ │ │ │ │ └── network
│ │ │ │ │ └── if-pre-up.d
│ │ │ │ │ └── wait-carrier.sh
│ │ │ ├── manifest-renesas.yaml
│ │ │ ├── buildroot_defconfig
│ │ │ └── build_fits.sh
│ │ ├── ti_j784s4xevm
│ │ │ ├── data
│ │ │ │ └── .gitkeep
│ │ │ └── manifest.yaml
│ │ ├── build_bundle.sh
│ │ └── test
│ │ │ ├── data
│ │ │ └── kernel
│ │ │ └── manifest.yaml
│ ├── jumpstarter_driver_flashers
│ │ └── __init__.py
│ ├── .gitignore
│ └── examples
│ │ └── exporter.yaml
├── jumpstarter-driver-gpiod
│ ├── jumpstarter_driver_gpiod
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ └── conftest.py
│ ├── example
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-http
│ ├── jumpstarter_driver_http
│ │ ├── __init__.py
│ │ └── py.typed
│ └── pyproject.toml
├── jumpstarter-driver-iscsi
│ ├── jumpstarter_driver_iscsi
│ │ ├── py.typed
│ │ └── __init__.py
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-power
│ ├── jumpstarter_driver_power
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ ├── common.py
│ │ └── client_test.py
│ ├── README.md
│ └── pyproject.toml
├── jumpstarter-driver-qemu
│ ├── jumpstarter_driver_qemu
│ │ ├── __init__.py
│ │ ├── py.typed
│ │ └── client.py
│ ├── images
│ │ └── .gitignore
│ └── README.md
├── jumpstarter-driver-snmp
│ ├── jumpstarter_driver_snmp
│ │ ├── __init__.py
│ │ └── client.py
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-ssh
│ ├── jumpstarter_driver_ssh
│ │ └── __init__.py
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-tftp
│ ├── jumpstarter_driver_tftp
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ └── driver_test.py
│ ├── test.txt
│ ├── examples
│ │ ├── exporter.yaml
│ │ └── tftp_test.py
│ └── pyproject.toml
├── jumpstarter-driver-tmt
│ ├── jumpstarter_driver_tmt
│ │ ├── __init__.py
│ │ └── driver.py
│ ├── .gitignore
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-uboot
│ ├── jumpstarter_driver_uboot
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ ├── common.py
│ │ └── driver.py
│ ├── README.md
│ └── pyproject.toml
├── jumpstarter-cli-driver
│ ├── README.md
│ ├── jumpstarter_cli_driver
│ │ ├── __main__.py
│ │ ├── driver_test.py
│ │ ├── __init__.py
│ │ └── driver.py
│ └── pyproject.toml
├── jumpstarter-driver-dutlink
│ ├── jumpstarter_driver_dutlink
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ └── conftest.py
│ ├── examples
│ │ └── exporter.yaml
│ └── README.md
├── jumpstarter-driver-network
│ └── jumpstarter_driver_network
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ ├── streams
│ │ └── __init__.py
│ │ ├── adapters
│ │ ├── __init__.py
│ │ ├── pexpect.py
│ │ ├── dbus.py
│ │ ├── fabric.py
│ │ ├── novnc_test.py
│ │ └── portforward.py
│ │ └── conftest.py
├── jumpstarter-driver-opendal
│ ├── jumpstarter_driver_opendal
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ └── conftest.py
│ └── pyproject.toml
├── jumpstarter-driver-pyserial
│ ├── jumpstarter_driver_pyserial
│ │ ├── py.typed
│ │ └── __init__.py
│ └── pyproject.toml
├── jumpstarter-driver-ridesx
│ ├── jumpstarter_driver_ridesx
│ │ └── __init__.py
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-sdwire
│ ├── jumpstarter_driver_sdwire
│ │ ├── __init__.py
│ │ ├── py.typed
│ │ └── driver_test.py
│ ├── pyproject.toml
│ └── README.md
├── jumpstarter-driver-shell
│ ├── jumpstarter_driver_shell
│ │ └── __init__.py
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-tasmota
│ ├── jumpstarter_driver_tasmota
│ │ ├── py.typed
│ │ ├── __init__.py
│ │ └── driver_test.py
│ └── pyproject.toml
├── jumpstarter-driver-yepkit
│ ├── jumpstarter_driver_yepkit
│ │ ├── __init__.py
│ │ ├── py.typed
│ │ ├── driver_test.py
│ │ └── conftest.py
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-composite
│ ├── jumpstarter_driver_composite
│ │ ├── __init__.py
│ │ └── py.typed
│ ├── README.md
│ └── pyproject.toml
├── jumpstarter-driver-corellium
│ ├── jumpstarter_driver_corellium
│ │ ├── __init__.py
│ │ ├── corellium
│ │ │ ├── __init__.py
│ │ │ ├── exceptions.py
│ │ │ └── types.py
│ │ └── client.py
│ ├── fixtures
│ │ └── http
│ │ │ ├── get-instance-state-200.txt
│ │ │ ├── json-error.json
│ │ │ ├── create-instance-200.json
│ │ │ ├── get-instance-console-url-200.json
│ │ │ ├── login-200.json
│ │ │ ├── get-instance-console-url-400.json
│ │ │ ├── create-instance-400.json
│ │ │ ├── get-projects-404.json
│ │ │ ├── get-instance-404.json
│ │ │ ├── 403.json
│ │ │ ├── delete-instance-404.json
│ │ │ ├── get-models-200.json
│ │ │ └── get-projects-200.json
│ ├── examples
│ │ └── exporter.yml
│ └── pyproject.toml
├── jumpstarter-driver-energenie
│ ├── jumpstarter_driver_energenie
│ │ └── __init__.py
│ ├── .gitignore
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-probe-rs
│ ├── jumpstarter_driver_probe_rs
│ │ ├── __init__.py
│ │ └── driver_test.py
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
├── jumpstarter-driver-ssh-mitm
│ ├── jumpstarter_driver_ssh_mitm
│ │ └── __init__.py
│ └── examples
│ │ └── exporter.yaml
├── jumpstarter-driver-ustreamer
│ ├── jumpstarter_driver_ustreamer
│ │ ├── __init__.py
│ │ ├── py.typed
│ │ ├── driver_test.py
│ │ ├── client.py
│ │ └── common.py
│ ├── pyproject.toml
│ └── README.md
├── jumpstarter-all
│ ├── jumpstarter_all
│ │ └── noop_test.py
│ └── README.md
├── jumpstarter-driver-http-power
│ ├── .gitignore
│ ├── jumpstarter_driver_http_power
│ │ └── __init__.py
│ ├── examples
│ │ └── exporter.yaml
│ └── pyproject.toml
└── jumpstarter-driver-vnc
│ ├── jumpstarter_driver_vnc
│ ├── __init__.py
│ └── driver.py
│ ├── examples
│ └── exporter.yaml
│ └── pyproject.toml
├── docs
├── source
│ ├── _static
│ │ ├── js
│ │ │ └── .gitignore
│ │ ├── img
│ │ │ ├── avatar.png
│ │ │ └── favicon.png
│ │ └── css
│ │ │ └── custom.css
│ ├── reference
│ │ ├── package-apis
│ │ │ ├── drivers
│ │ │ │ ├── ble.md
│ │ │ │ ├── can.md
│ │ │ │ ├── http.md
│ │ │ │ ├── qemu.md
│ │ │ │ ├── snmp.md
│ │ │ │ ├── ssh.md
│ │ │ │ ├── tftp.md
│ │ │ │ ├── tmt.md
│ │ │ │ ├── vnc.md
│ │ │ │ ├── dutlink.md
│ │ │ │ ├── gpiod.md
│ │ │ │ ├── network.md
│ │ │ │ ├── opendal.md
│ │ │ │ ├── power.md
│ │ │ │ ├── sdwire.md
│ │ │ │ ├── shell.md
│ │ │ │ ├── tasmota.md
│ │ │ │ ├── uboot.md
│ │ │ │ ├── yepkit.md
│ │ │ │ ├── corellium.md
│ │ │ │ ├── energenie.md
│ │ │ │ ├── flashers.md
│ │ │ │ ├── probe-rs.md
│ │ │ │ ├── pyserial.md
│ │ │ │ ├── ustreamer.md
│ │ │ │ ├── http-power.md
│ │ │ │ ├── dbus.yaml
│ │ │ │ ├── proxy.yaml
│ │ │ │ ├── sdwire.yaml
│ │ │ │ ├── ustreamer.yaml
│ │ │ │ ├── opendal.yaml
│ │ │ │ └── uboot.yaml
│ │ │ ├── exceptions.md
│ │ │ └── index.md
│ │ ├── man-pages
│ │ │ ├── jmp.md
│ │ │ ├── index.md
│ │ │ └── j.md
│ │ └── index.md
│ ├── contributing
│ │ └── images
│ │ │ ├── rpc.png
│ │ │ ├── router.png
│ │ │ └── architecture.png
│ ├── _templates
│ │ ├── warning.html
│ │ ├── head.html
│ │ └── page.html
│ ├── getting-started
│ │ ├── installation
│ │ │ ├── index.md
│ │ │ └── service
│ │ │ │ └── index.md
│ │ ├── index.md
│ │ ├── configuration
│ │ │ └── index.md
│ │ └── guides
│ │ │ └── index.md
│ └── introduction
│ │ └── clients.md
├── multiversion.sh
└── Makefile
├── __templates__
└── driver
│ ├── jumpstarter_driver
│ ├── __init__.py.tmpl
│ ├── driver_test.py.tmpl
│ ├── client.py.tmpl
│ └── driver.py.tmpl
│ ├── .gitignore.tmpl
│ ├── examples
│ └── exporter.yaml.tmpl
│ └── pyproject.toml.tmpl
├── examples
├── automotive
│ ├── jumpstarter_example_automotive
│ │ ├── __init__.py
│ │ ├── hello_test.py
│ │ └── hello.py
│ ├── README.md
│ └── pyproject.toml
└── soc-pytest
│ ├── jumpstarter_example_soc_pytest
│ ├── test_booted_ok.jpeg
│ ├── test_booting_empty_ok.jpeg
│ ├── test_booting_rainbow_ok.jpeg
│ ├── test_booting_raspberries_ok.jpeg
│ ├── image
│ │ └── scripts
│ │ │ ├── prepare-latest-raw
│ │ │ └── download-latest-raspbian
│ └── exporter.yaml
│ └── pyproject.toml
├── .gitattributes
├── Dockerfile.utils
├── CONTRIBUTING.md
├── .devcontainer
└── Dockerfile
├── buf.gen.yaml
├── .pre-commit-config.yaml
├── .github
├── workflows
│ ├── typos.yaml
│ ├── ruff.yaml
│ ├── e2e.yaml
│ ├── trigger-packages-index.yaml
│ ├── build_oci_bundle.yaml
│ └── pr_analytics.yaml
└── dependabot.yml
├── .vscode
├── settings.json
└── extensions.json
├── .devfile
└── Containerfile
├── Dockerfile
├── kind_config.yaml
├── .devfile.yaml
├── conftest.py
└── assets
└── bolt.svg
/.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-testing/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/hatch-pin-jumpstarter/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-imagehash/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter/README.md:
--------------------------------------------------------------------------------
1 | # Jumpstarter Core
--------------------------------------------------------------------------------
/docs/source/_static/js/.gitignore:
--------------------------------------------------------------------------------
1 | version_array.js
--------------------------------------------------------------------------------
/packages/jumpstarter-cli/jumpstarter_cli/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/config/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/streams/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/__templates__/driver/jumpstarter_driver/__init__.py.tmpl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli/README.md:
--------------------------------------------------------------------------------
1 | # The Jumpstarter CLI
--------------------------------------------------------------------------------
/packages/jumpstarter-testing/jumpstarter_testing/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/automotive/jumpstarter_example_automotive/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-admin/README.md:
--------------------------------------------------------------------------------
1 | # Jumpstarter Admin CLI
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-common/jumpstarter_cli_common/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-can/jumpstarter_driver_can/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-imagehash/jumpstarter_imagehash/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/jumpstarter_protocol/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/hatch-pin-jumpstarter/src/hatch_pin_jumpstarter/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-common/jumpstarter_cli_common/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ble/jumpstarter_driver_ble/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-can/jumpstarter_driver_can/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/rcar_s4/data/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-gpiod/jumpstarter_driver_gpiod/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-http/jumpstarter_driver_http/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-http/jumpstarter_driver_http/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-iscsi/jumpstarter_driver_iscsi/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-power/jumpstarter_driver_power/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-qemu/jumpstarter_driver_qemu/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-qemu/jumpstarter_driver_qemu/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ssh/jumpstarter_driver_ssh/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-uboot/jumpstarter_driver_uboot/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-common/README.md:
--------------------------------------------------------------------------------
1 | # Jumpstarter CLI Common Utils
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-driver/README.md:
--------------------------------------------------------------------------------
1 | # Jumpstarter Driver CLI
2 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-gpiod/jumpstarter_driver_gpiod/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-iscsi/jumpstarter_driver_iscsi/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-power/jumpstarter_driver_power/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-qemu/images/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-shell/jumpstarter_driver_shell/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tasmota/jumpstarter_driver_tasmota/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tftp/test.txt:
--------------------------------------------------------------------------------
1 | Hello from TFTP streaming test!
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-uboot/jumpstarter_driver_uboot/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-kubernetes/README.md:
--------------------------------------------------------------------------------
1 | # Jumpstarter Kubernetes Library
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-composite/jumpstarter_driver_composite/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-composite/jumpstarter_driver_composite/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-energenie/jumpstarter_driver_energenie/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/data/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/ti_j784s4xevm/data/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-probe-rs/jumpstarter_driver_probe_rs/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ssh-mitm/jumpstarter_driver_ssh_mitm/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tasmota/jumpstarter_driver_tasmota/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/__templates__/driver/.gitignore.tmpl:
--------------------------------------------------------------------------------
1 | __pycache__/
2 | .coverage
3 | coverage.xml
4 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt:
--------------------------------------------------------------------------------
1 | on
2 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/json-error.json:
--------------------------------------------------------------------------------
1 | {"token": "a}
2 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/protocol_test.py:
--------------------------------------------------------------------------------
1 | def test_protocol():
2 | pass
3 |
--------------------------------------------------------------------------------
/packages/jumpstarter-all/jumpstarter_all/noop_test.py:
--------------------------------------------------------------------------------
1 | def test_nothing():
2 | pass
3 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest.yaml:
--------------------------------------------------------------------------------
1 | manifest-ti.yaml
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tmt/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
2 | .coverage
3 | coverage.xml
4 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-energenie/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
2 | .coverage
3 | coverage.xml
4 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
2 | .coverage
3 | coverage.xml
4 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-http-power/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
2 | .coverage
3 | coverage.xml
4 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/ble.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-ble/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/can.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-can/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/http.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-http/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/qemu.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-qemu/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/snmp.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-snmp/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/ssh.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-ssh/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/tftp.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-tftp/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/tmt.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-tmt/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/vnc.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-vnc/README.md
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ble/jumpstarter_driver_ble/driver_test.py:
--------------------------------------------------------------------------------
1 | # TODO: add some test if possible
2 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/__init__.py:
--------------------------------------------------------------------------------
1 | CHUNK_SIZE = 1024 * 1024 * 4 # 4MB
2 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/dutlink.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-dutlink/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/gpiod.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-gpiod/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/network.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-network/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/opendal.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-opendal/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/power.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-power/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/sdwire.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-sdwire/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/shell.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-shell/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/tasmota.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-tasmota/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/uboot.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-uboot/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/yepkit.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-yepkit/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/corellium.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-corellium/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/energenie.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-energenie/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/flashers.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-flashers/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/probe-rs.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-probe-rs/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/pyserial.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-pyserial/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/ustreamer.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-ustreamer/README.md
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/http-power.md:
--------------------------------------------------------------------------------
1 | ../../../../../packages/jumpstarter-driver-http-power/README.md
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | packages/jumpstarter-driver-flashers/oci_bundles/rcar_s4/data/flasher.itb filter=lfs diff=lfs merge=lfs -text
2 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-vnc/jumpstarter_driver_vnc/__init__.py:
--------------------------------------------------------------------------------
1 | from .client import VNClient
2 |
3 | VNClient = VNClient
4 |
--------------------------------------------------------------------------------
/docs/source/_static/img/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/docs/source/_static/img/avatar.png
--------------------------------------------------------------------------------
/docs/source/_static/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/docs/source/_static/img/favicon.png
--------------------------------------------------------------------------------
/packages/jumpstarter-imagehash/jumpstarter_imagehash/__init__.py:
--------------------------------------------------------------------------------
1 | from .imagehash import ImageHash
2 |
3 | ImageHash = ImageHash
4 |
--------------------------------------------------------------------------------
/docs/source/reference/man-pages/jmp.md:
--------------------------------------------------------------------------------
1 | ```{eval-rst}
2 | .. click:: jumpstarter_cli.jmp:jmp
3 | :prog: jmp
4 | :nested: full
5 | ```
--------------------------------------------------------------------------------
/docs/source/contributing/images/rpc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/docs/source/contributing/images/rpc.png
--------------------------------------------------------------------------------
/examples/automotive/jumpstarter_example_automotive/hello_test.py:
--------------------------------------------------------------------------------
1 | from .hello import main
2 |
3 |
4 | def test_hello():
5 | main()
6 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "7f4f241c-821f-4219-905f-c3b50b0db5dd"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json:
--------------------------------------------------------------------------------
1 | {
2 | "url": "wss://api-host/port-cons-1"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/jumpstarter-testing/jumpstarter_testing/__init__.py:
--------------------------------------------------------------------------------
1 | from .pytest import JumpstarterTest
2 |
3 | __all__ = ["JumpstarterTest"]
4 |
--------------------------------------------------------------------------------
/docs/source/contributing/images/router.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/docs/source/contributing/images/router.png
--------------------------------------------------------------------------------
/Dockerfile.utils:
--------------------------------------------------------------------------------
1 | FROM fedora:42
2 | RUN dnf install -y kubernetes-client easy-rsa trurl && \
3 | dnf clean all && \
4 | rm -rf /var/cache/dnf
5 |
--------------------------------------------------------------------------------
/docs/source/contributing/images/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/docs/source/contributing/images/architecture.png
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/login-200.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "session-token",
3 | "expiration": "2022-03-20T01:50:10.000Z"
4 | }
5 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-http-power/jumpstarter_driver_http_power/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Jumpstarter developers
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/exporter/__init__.py:
--------------------------------------------------------------------------------
1 | from .exporter import Exporter
2 | from .session import Session
3 |
4 | __all__ = ["Session", "Exporter"]
5 |
--------------------------------------------------------------------------------
/examples/automotive/jumpstarter_example_automotive/hello.py:
--------------------------------------------------------------------------------
1 | def main():
2 | print("Hello from automotive!")
3 |
4 |
5 | if __name__ == "__main__":
6 | main()
7 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/config/shell.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel
2 |
3 |
4 | class ShellConfigV1Alpha1(BaseModel):
5 | use_profiles: bool = False
6 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/__init__.py:
--------------------------------------------------------------------------------
1 | from .websocket import WebsocketServerStream
2 |
3 | __all__ = ["WebsocketServerStream"]
4 |
--------------------------------------------------------------------------------
/packages/jumpstarter-testing/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | pytest_plugins = ["pytester"]
4 |
5 |
6 | @pytest.fixture
7 | def anyio_backend():
8 | return "asyncio"
9 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/dbus.yaml:
--------------------------------------------------------------------------------
1 | type: "jumpstarter_driver_network.driver.DbusNetwork"
2 | config:
3 | kind: "system" # which bus to connect to, system or session
4 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json:
--------------------------------------------------------------------------------
1 | {
2 | "error":"not a valid type",
3 | "errorID":"UserError",
4 | "field":"type"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/driver/__init__.py:
--------------------------------------------------------------------------------
1 | from .base import Driver
2 | from .decorators import export, exportstream
3 |
4 | __all__ = ["Driver", "export", "exportstream"]
5 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/exceptions.md:
--------------------------------------------------------------------------------
1 | # Exceptions
2 |
3 | ## API Reference
4 |
5 | ```{eval-rst}
6 | .. automodule:: jumpstarter.common.exceptions
7 | :members:
8 | ```
9 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json:
--------------------------------------------------------------------------------
1 | {
2 | "error": "Unsupported device model",
3 | "errorID": "UserError",
4 | "field": "flavor"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json:
--------------------------------------------------------------------------------
1 | {
2 | "error": "Found no matching Projects",
3 | "errorID": "UserError",
4 | "field": "Project"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/util/__init__.py:
--------------------------------------------------------------------------------
1 | from .async_custom_object_api import AbstractAsyncCustomObjectApi
2 |
3 | __all__ = ["AbstractAsyncCustomObjectApi"]
4 |
--------------------------------------------------------------------------------
/examples/soc-pytest/jumpstarter_example_soc_pytest/test_booted_ok.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/examples/soc-pytest/jumpstarter_example_soc_pytest/test_booted_ok.jpeg
--------------------------------------------------------------------------------
/packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_a.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_a.jpeg
--------------------------------------------------------------------------------
/packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_b.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_b.jpeg
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/get-instance-404.json:
--------------------------------------------------------------------------------
1 | {
2 | "error": "No instance associated with this value",
3 | "errorID": "UserError",
4 | "field": "InstanceId"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py:
--------------------------------------------------------------------------------
1 | from jumpstarter_driver_composite.client import CompositeClient
2 |
3 |
4 | class CorelliumClient(CompositeClient):
5 | pass
6 |
--------------------------------------------------------------------------------
/examples/soc-pytest/jumpstarter_example_soc_pytest/test_booting_empty_ok.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/examples/soc-pytest/jumpstarter_example_soc_pytest/test_booting_empty_ok.jpeg
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/client/exceptions.py:
--------------------------------------------------------------------------------
1 | from jumpstarter.common import exceptions
2 |
3 |
4 | class LeaseError(exceptions.JumpstarterException):
5 | """Raised when a lease operation fails."""
6 |
--------------------------------------------------------------------------------
/examples/soc-pytest/jumpstarter_example_soc_pytest/test_booting_rainbow_ok.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/examples/soc-pytest/jumpstarter_example_soc_pytest/test_booting_rainbow_ok.jpeg
--------------------------------------------------------------------------------
/packages/jumpstarter-cli/jumpstarter_cli/__main__.py:
--------------------------------------------------------------------------------
1 | """Allow running Jumpstarter through `python -m jumpstarter_cli`."""
2 |
3 | from .jmp import jmp
4 |
5 | if __name__ == "__main__":
6 | jmp(prog_name="jmp")
7 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/client/__init__.py:
--------------------------------------------------------------------------------
1 | from .base import DriverClient
2 | from .client import client_from_path
3 | from .lease import Lease
4 |
5 | __all__ = ["DriverClient", "client_from_path", "Lease"]
6 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/config/tls.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel, Field
2 |
3 |
4 | class TLSConfigV1Alpha1(BaseModel):
5 | ca: str = Field(default="")
6 | insecure: bool = Field(default=False)
7 |
--------------------------------------------------------------------------------
/examples/soc-pytest/jumpstarter_example_soc_pytest/test_booting_raspberries_ok.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jumpstarter-dev/jumpstarter/HEAD/examples/soc-pytest/jumpstarter_example_soc_pytest/test_booting_raspberries_ok.jpeg
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/403.json:
--------------------------------------------------------------------------------
1 | {
2 | "error": "Invalid or missing authorization token",
3 | "errorID": "PermissionDenied",
4 | "originalError": "Invalid or missing authorization token"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/overlay/etc/udev/rules.d/10-rename-tsn0.rules:
--------------------------------------------------------------------------------
1 | # rename Renesas S4 main interface tsn0 to eth0 to unify setup
2 | SUBSYSTEM=="net", ACTION=="add", KERNEL=="tsn0", NAME="eth0"
3 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/rcar_s4/overlay/etc/udev/rules.d/10-rename-tsn0.rules:
--------------------------------------------------------------------------------
1 | # rename Renesas S4 main interface tsn0 to eth0 to unify setup
2 | SUBSYSTEM=="net", ACTION=="add", KERNEL=="tsn0", NAME="eth0"
3 |
--------------------------------------------------------------------------------
/docs/source/_templates/warning.html:
--------------------------------------------------------------------------------
1 |
2 |
Warning
3 |
This documentation is actively being updated as the project evolves and may not be complete in all areas.
4 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__main__.py:
--------------------------------------------------------------------------------
1 | """Allow running Jumpstarter through `python -m jumpstarter_cli_admin`."""
2 |
3 | from . import admin
4 |
5 | if __name__ == "__main__":
6 | admin(prog_name="jmp-admin")
7 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/__main__.py:
--------------------------------------------------------------------------------
1 | """Allow running Jumpstarter through `python -m jumpstarter_cli_driver`."""
2 |
3 | from . import driver
4 |
5 | if __name__ == "__main__":
6 | driver(prog_name="jmp-driver")
7 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/common_pb2_grpc.py:
--------------------------------------------------------------------------------
1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2 | """Client and server classes corresponding to protobuf-defined services."""
3 | import grpc
4 |
5 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2_grpc.py:
--------------------------------------------------------------------------------
1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2 | """Client and server classes corresponding to protobuf-defined services."""
3 | import grpc
4 |
5 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/proxy.yaml:
--------------------------------------------------------------------------------
1 | children:
2 | proxy:
3 | ref: "foo.bar.power"
4 | foo:
5 | children:
6 | bar:
7 | children:
8 | power:
9 | type: "jumpstarter_driver_power.driver.MockPower"
10 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/common/__init__.py:
--------------------------------------------------------------------------------
1 | from .metadata import Metadata
2 | from .tempfile import TemporarySocket, TemporaryTcpListener, TemporaryUnixListener
3 |
4 | __all__ = ["Metadata", "TemporarySocket", "TemporaryUnixListener", "TemporaryTcpListener"]
5 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Thank you for your interest in contributing to Jumpstarter, we are an open
4 | community and we welcome contributions.
5 |
6 | For a complete contribution guide, please refer to our
7 | [documentation](https://jumpstarter.dev/main/contributing.html).
8 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-common/jumpstarter_cli_common/blocking.py:
--------------------------------------------------------------------------------
1 | from asyncio import run
2 | from functools import wraps
3 |
4 |
5 | def blocking(f):
6 | @wraps(f)
7 | def wrapper(*args, **kwargs):
8 | return run(f(*args, **kwargs))
9 |
10 | return wrapper
11 |
--------------------------------------------------------------------------------
/packages/jumpstarter-all/README.md:
--------------------------------------------------------------------------------
1 | # jumpstarter-all
2 |
3 | The Jumpstarter project is a collection of tools and services to help automate
4 | the testing of/on hardware devices.
5 |
6 | This is a meta-package that pulls installation of all the Python modules
7 | produced in the Jumpstarter project.
8 |
9 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-power/jumpstarter_driver_power/common.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel
2 |
3 |
4 | class PowerReading(BaseModel):
5 | voltage: float
6 | current: float
7 |
8 | @property
9 | def apparent_power(self):
10 | return self.voltage * self.current
11 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/driver_test.py:
--------------------------------------------------------------------------------
1 | from .driver import Ykush
2 | from jumpstarter.common.utils import serve
3 |
4 |
5 | def test_drivers_yepkit():
6 | instance = Ykush()
7 |
8 | with serve(instance) as client:
9 | client.on()
10 | client.off()
11 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json:
--------------------------------------------------------------------------------
1 | {
2 | "error": "Instance with instanceId=7f4f241c-821f-4219-905f-c3b50b0db5dd not found",
3 | "errorID": "InstanceNotFound",
4 | "name": "Instance",
5 | "params": {
6 | "instanceId": "7f4f241c-821f-4219-905f-c3b50b0db5dd"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver_test.py:
--------------------------------------------------------------------------------
1 | from click.testing import CliRunner
2 |
3 | from . import driver
4 |
5 |
6 | def test_list_drivers():
7 | runner = CliRunner()
8 |
9 | result = runner.invoke(
10 | driver,
11 | ["list"],
12 | )
13 | assert result.exit_code == 0
14 |
--------------------------------------------------------------------------------
/examples/automotive/README.md:
--------------------------------------------------------------------------------
1 | # Jumpstarter Automotive Example
2 |
3 | This example aims to demonstrate Jumpstarter in an automotive context.
4 |
5 | The following drivers will be utilized:
6 | - SSH
7 | - CAN/ISO-TP (UDS)
8 |
9 | This example requires the following hardware:
10 | - 2x Raspberry Pi 4
11 | - 2x Waveshare CAN FD Hat
12 |
--------------------------------------------------------------------------------
/__templates__/driver/examples/exporter.yaml.tmpl:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | example:
10 | type: jumpstarter_driver_${DRIVER_NAME}.driver.${DRIVER_CLASS}
11 |
12 |
--------------------------------------------------------------------------------
/__templates__/driver/jumpstarter_driver/driver_test.py.tmpl:
--------------------------------------------------------------------------------
1 | from jumpstarter.common.utils import serve
2 |
3 | from .driver import ${DRIVER_CLASS}
4 |
5 |
6 | def test_drivers_${DRIVER_NAME}():
7 | instance = ${DRIVER_CLASS}()
8 |
9 | with serve(instance) as client:
10 | assert client.state().ok
11 | _ = client.snapshot()
12 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli/jumpstarter_cli/config.py:
--------------------------------------------------------------------------------
1 | import click
2 |
3 | from .config_client import config_client
4 | from .config_exporter import config_exporter
5 |
6 |
7 | @click.group
8 | def config():
9 | """
10 | Manage local configurations
11 | """
12 | pass
13 |
14 |
15 | config.add_command(config_client)
16 | config.add_command(config_exporter)
17 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py:
--------------------------------------------------------------------------------
1 | """
2 | Corellium API client exceptions module
3 | """
4 | from jumpstarter.common.exceptions import JumpstarterException
5 |
6 |
7 | class CorelliumApiException(JumpstarterException):
8 | """
9 | Exception raised when something goes wrong with Corellium's API.
10 | """
11 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/sdwire.yaml:
--------------------------------------------------------------------------------
1 | type: "jumpstarter_driver_sdwire.driver.SDWire"
2 | config:
3 | # optional serial number of the sd-wire device
4 | # the first one found would be used if unset
5 | serial: "sdw-00001"
6 | # optional path to the block device exposed by sd-wire
7 | # automatically detected if unset
8 | storage_device: "/dev/disk/by-diskseq/1"
9 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/ustreamer.yaml:
--------------------------------------------------------------------------------
1 | type: "jumpstarter_driver_ustreamer.driver.UStreamer"
2 | config:
3 | # name or path of the ustreamer executable
4 | # defaults to finding ustreamer from path
5 | executable: "ustreamer"
6 | args: # extra arguments to pass to ustreamer
7 | brightness: auto # --brightness=auto
8 | contrast: default # --contract=default
9 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/client/adapters.py:
--------------------------------------------------------------------------------
1 | from contextlib import contextmanager
2 | from functools import wraps
3 |
4 |
5 | def blocking(f):
6 | @wraps(f)
7 | @contextmanager
8 | def wrapper(*args, **kwargs):
9 | with kwargs["client"].portal.wrap_async_context_manager(f(*args, **kwargs)) as res:
10 | yield res
11 |
12 | return wrapper
13 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "type": "iot",
4 | "name": "rpi4b",
5 | "flavor": "rpi4b",
6 | "description": "Raspberry Pi 4",
7 | "model": "rpi4b",
8 | "peripherals": false,
9 | "quotas": {
10 | "cores": 4,
11 | "cpus": 4
12 | }
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/vscode/devcontainers/base:bookworm
2 |
3 | ENV PYTHONUNBUFFERED=True
4 | ENV UV_LINK_MODE=copy
5 |
6 | WORKDIR /opt
7 |
8 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
9 | COPY --from=ghcr.io/astral-sh/uv:latest /uvx /bin/uvx
10 | COPY ./.python-version ./
11 |
12 | # Install required tools for development
13 | RUN apt-get update && apt-get install -y iperf3 libusb-dev
--------------------------------------------------------------------------------
/docs/source/_templates/head.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/buf.gen.yaml:
--------------------------------------------------------------------------------
1 | version: v2
2 | managed:
3 | enabled: true
4 | plugins:
5 | - remote: buf.build/protocolbuffers/python:v30.1
6 | out: ./packages/jumpstarter-protocol/jumpstarter_protocol
7 | - remote: buf.build/grpc/python
8 | out: ./packages/jumpstarter-protocol/jumpstarter_protocol
9 | inputs:
10 | - git_repo: https://github.com/jumpstarter-dev/jumpstarter-protocol.git
11 | branch: main
12 | subdir: proto
13 |
--------------------------------------------------------------------------------
/docs/source/getting-started/installation/index.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | This section provides guidance on installing Jumpstarter components in your
4 | environment. The guides cover:
5 |
6 | - [Packages](packages.md): Installing Jumpstarter software packages
7 | - [Service](service/index.md): Setting up Jumpstarter as a Kubernetes service
8 |
9 | ```{toctree}
10 | :maxdepth: 1
11 | :hidden:
12 | packages.md
13 | service/index.md
14 | ```
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-dutlink/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | # /etc/jumpstarter/exporters/dutlink.yaml
2 | apiVersion: jumpstarter.dev/v1alpha1
3 | kind: ExporterConfig
4 | metadata:
5 | namespace: default
6 | name: demo
7 | endpoint: ""
8 | token: ""
9 | export:
10 | dutlink:
11 | type: jumpstarter_driver_dutlink.driver.Dutlink
12 | config:
13 | storage_device: "/dev/null" # TODO: replace with real storage device
14 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-energenie/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | power:
10 | type: jumpstarter_driver_energenie.driver.EnerGenie
11 | config:
12 | host: "192.168.1.51"
13 | password: "1"
14 | slot: 1
15 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | default_stages: [pre-commit]
2 | repos:
3 | - repo: https://github.com/astral-sh/ruff-pre-commit
4 | rev: v0.9.2
5 | hooks:
6 | - id: ruff
7 | name: Ruff Check
8 | description: "Run 'ruff check' for extremely fast Python linting"
9 | args: [ --fix ]
10 |
11 | - id: ruff-format
12 | name: Ruff Format
13 | description: "Run 'ruff format' for extremely fast Python formatting"
--------------------------------------------------------------------------------
/examples/automotive/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-example-automotive"
3 | version = "0.1.0"
4 | description = ""
5 | authors = [
6 | { name = "Kirk Brauer", email = "kbrauer@hatci.com" },
7 | { name = "Nick Cao", email = "ncao@redhat.com" },
8 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
9 | ]
10 | readme = "README.md"
11 | license = "Apache-2.0"
12 | requires-python = ">=3.11"
13 | dependencies = ["jumpstarter"]
14 |
--------------------------------------------------------------------------------
/.github/workflows/typos.yaml:
--------------------------------------------------------------------------------
1 | name: Spell Check
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - main
8 | - release-*
9 | pull_request:
10 | merge_group:
11 |
12 | permissions:
13 | contents: read
14 |
15 | jobs:
16 | typos:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/checkout@v4
20 | - name: Run typos
21 | uses: crate-ci/typos@0f0ccba9ed1df83948f0c15026e4f5ccfce46109 # v1.32.0
22 |
--------------------------------------------------------------------------------
/__templates__/driver/jumpstarter_driver/client.py.tmpl:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 |
3 | from jumpstarter.client import DriverClient
4 |
5 |
6 | @dataclass(kw_only=True)
7 | class ${DRIVER_CLASS}Client(DriverClient):
8 | """
9 | Client interface for ...
10 |
11 | This client provides methods to
12 | """
13 |
14 | def method1(self):
15 | self.call("method1")
16 |
17 | def method2(self):
18 | self.call("method2")
19 |
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-probe-rs/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | probe:
10 | type: jumpstarter_driver_probe_rs.driver.ProbeRs
11 | config:
12 | probe_rs_path: /home/majopela/.cargo/bin/probe-rs
13 | protocol: "swd"
14 | speed: 4000
15 |
16 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/common/metadata.py:
--------------------------------------------------------------------------------
1 | from dataclasses import field
2 | from uuid import UUID, uuid4
3 |
4 | from pydantic.dataclasses import dataclass
5 |
6 |
7 | @dataclass(kw_only=True, slots=True)
8 | class Metadata:
9 | uuid: UUID = field(default_factory=uuid4)
10 | labels: dict[str, str] = field(default_factory=dict)
11 |
12 | @property
13 | def name(self):
14 | return self.labels.get("jumpstarter.dev/name", "unknown")
15 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/common/serde.py:
--------------------------------------------------------------------------------
1 | from typing import Any
2 |
3 | from google.protobuf import json_format, struct_pb2
4 | from pydantic import TypeAdapter
5 |
6 | adapter = TypeAdapter(Any)
7 |
8 |
9 | def encode_value(v: Any):
10 | return json_format.ParseDict(adapter.dump_python(v, mode="json"), struct_pb2.Value())
11 |
12 |
13 | def decode_value(v: struct_pb2.Value) -> Any:
14 | return adapter.validate_python(json_format.MessageToDict(v))
15 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli/jumpstarter_cli/__init__.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import truststore
4 |
5 | # if we are running in MacOS avoid injecting system certificates to avoid
6 | # https://github.com/jumpstarter-dev/jumpstarter/issues/362
7 | # also allow to force the system certificates injection with
8 | # JUMPSTARTER_FORCE_SYSTEM_CERTS=1
9 | if os.uname().sysname != "Darwin" or os.environ.get("JUMPSTARTER_FORCE_SYSTEM_CERTS") == "1":
10 | truststore.inject_into_ssl()
11 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/__init__.py:
--------------------------------------------------------------------------------
1 | from .dbus import DbusAdapter
2 | from .fabric import FabricAdapter
3 | from .novnc import NovncAdapter
4 | from .pexpect import PexpectAdapter
5 | from .portforward import TcpPortforwardAdapter, UnixPortforwardAdapter
6 |
7 | __all__ = [
8 | "DbusAdapter",
9 | "FabricAdapter",
10 | "NovncAdapter",
11 | "PexpectAdapter",
12 | "TcpPortforwardAdapter",
13 | "UnixPortforwardAdapter",
14 | ]
15 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/config/env.py:
--------------------------------------------------------------------------------
1 | # Common environment variables for client/exporter config
2 | JMP_CLIENT_CONFIG_HOME = "JMP_CLIENT_CONFIG_HOME"
3 | JMP_CLIENT_CONFIG = "JMP_CLIENT_CONFIG"
4 | JMP_NAMESPACE = "JMP_NAMESPACE"
5 | JMP_NAME = "JMP_NAME"
6 | JMP_ENDPOINT = "JMP_ENDPOINT"
7 | JMP_TOKEN = "JMP_TOKEN"
8 | JMP_DRIVERS_ALLOW = "JMP_DRIVERS_ALLOW"
9 | JUMPSTARTER_HOST = "JUMPSTARTER_HOST"
10 | JMP_LEASE = "JMP_LEASE"
11 |
12 | JMP_DISABLE_COMPRESSION = "JMP_DISABLE_COMPRESSION"
13 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.testing.pytestArgs": [
3 | "tests",
4 | "jumpstarter",
5 | "--cov",
6 | "--cov-report=html",
7 | "--cov-report=xml"
8 | ],
9 | "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
10 | "python.testing.unittestEnabled": false,
11 | "python.testing.pytestEnabled": true,
12 | "python.analysis.extraPaths": [
13 | "./contrib/*"
14 | ],
15 | "makefile.configureOnOpen": false
16 | }
--------------------------------------------------------------------------------
/docs/source/reference/man-pages/index.md:
--------------------------------------------------------------------------------
1 | # MAN Pages
2 |
3 | This section provides reference documentation for Jumpstarter's command-line
4 | interfaces. The documentation covers:
5 |
6 | - [`jmp`](jmp.md): Main command-line interface for Jumpstarter
7 | - [`j`](j.md): Shorthand utility for quick interactions with Jumpstarter
8 |
9 | These references support both local and distributed deployment modes of
10 | Jumpstarter.
11 |
12 | ```{toctree}
13 | :maxdepth: 1
14 | :hidden:
15 | jmp.md
16 | j.md
17 | ```
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/test_utils.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 |
4 | def json_equal(a: str, b: str) -> bool:
5 | def _parse(s: str):
6 | try:
7 | data = json.loads(s)
8 | except ValueError:
9 | return object()
10 | if isinstance(data, str):
11 | try:
12 | data = json.loads(data)
13 | except ValueError:
14 | pass
15 | return data
16 |
17 | return _parse(a) == _parse(b)
18 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-iscsi/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: iscsi-exporter
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | iscsi:
10 | type: jumpstarter_driver_iscsi.driver.ISCSI
11 | config:
12 | root_dir: "/var/lib/iscsi"
13 | iqn_prefix: "iqn.2024-06.dev.jumpstarter"
14 | target_name: "my-target"
15 | host: ""
16 | port: 3260
--------------------------------------------------------------------------------
/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/list.py:
--------------------------------------------------------------------------------
1 | from typing import Generic, Literal, TypeVar
2 |
3 | from pydantic import Field
4 |
5 | from .json import JsonBaseModel
6 |
7 | T = TypeVar("T")
8 |
9 |
10 | class V1Alpha1List(JsonBaseModel, Generic[T]):
11 | """A generic list result type."""
12 |
13 | api_version: Literal["jumpstarter.dev/v1alpha1"] = Field(alias="apiVersion", default="jumpstarter.dev/v1alpha1")
14 | items: list[T]
15 | kind: Literal["List"] = Field(default="List")
16 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/streams/blocking.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 |
3 | from anyio.abc import AnyByteStream
4 | from anyio.from_thread import BlockingPortal
5 |
6 |
7 | @dataclass(kw_only=True)
8 | class BlockingStream:
9 | stream: AnyByteStream
10 | portal: BlockingPortal
11 |
12 | def send(self, data: bytes) -> None:
13 | return self.portal.call(self.stream.send, data)
14 |
15 | def receive(self) -> bytes:
16 | return self.portal.call(self.stream.receive)
17 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli/jumpstarter_cli/cli_test.py:
--------------------------------------------------------------------------------
1 | from click.testing import CliRunner
2 |
3 | from .jmp import jmp
4 |
5 |
6 | def test_cli():
7 | runner = CliRunner()
8 | result = runner.invoke(jmp, [])
9 | for subcommand in [
10 | "config",
11 | "create",
12 | "delete",
13 | "driver",
14 | "get",
15 | "login",
16 | "run",
17 | "shell",
18 | "update",
19 | "version",
20 | ]:
21 | assert subcommand in result.output
22 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-snmp/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
4 | metadata:
5 | namespace: default
6 | name: demo
7 | tls:
8 | ca: ''
9 | insecure: true
10 | token:
11 | export:
12 | power:
13 | type: "jumpstarter_driver_snmp.driver.SNMPServer"
14 | config:
15 | host: "pdu.mgmt.com"
16 | user: "labuser"
17 | plug: 32
18 | oid: "1.3.6.1.4.1.13742.6.4.1.2.1.2.1"
19 |
--------------------------------------------------------------------------------
/.github/workflows/ruff.yaml:
--------------------------------------------------------------------------------
1 | name: Lint
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - main
8 | - release-*
9 | pull_request:
10 | merge_group:
11 |
12 | permissions:
13 | contents: read
14 |
15 | jobs:
16 | ruff:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/checkout@v4
20 | - name: Run ruff
21 | uses: astral-sh/ruff-action@84f83ecf9e1e15d26b7984c7ec9cf73d39ffc946 # v3.3.1
22 | with:
23 | version-file: pyproject.toml
24 |
--------------------------------------------------------------------------------
/docs/source/_static/css/custom.css:
--------------------------------------------------------------------------------
1 | .admonition.warning {
2 | margin-bottom: 2rem;
3 | }
4 |
5 | /* Hide the Furo attribution text */
6 | .made-with-furo {
7 | display: none !important;
8 | }
9 |
10 | /* Fix version name overflow in sidebar */
11 | .sidebar-brand .sidebar-brand-text {
12 | white-space: normal;
13 | word-break: break-word;
14 | }
15 |
16 | .sidebar-brand .sidebar-brand-text a {
17 | display: inline-block;
18 | max-width: 100%;
19 | overflow: hidden;
20 | text-overflow: ellipsis;
21 | }
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for more information:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 | # https://containers.dev/guide/dependabot
6 |
7 | version: 2
8 | updates:
9 | - package-ecosystem: "devcontainers"
10 | directory: "/"
11 | schedule:
12 | interval: weekly
13 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/opendal.yaml:
--------------------------------------------------------------------------------
1 | type: "jumpstarter_driver_opendal.driver.Opendal"
2 | config:
3 | # See https://docs.rs/opendal/latest/opendal/services/index.html
4 | # for list of supported services and their configuration parameters
5 | scheme: "fs"
6 | kwargs:
7 | root: "/tmp/jumpstarter"
8 | # Optional: automatically remove created files/directories when driver closes
9 | # Note: all tracked paths are normalized by stripping leading/trailing slashes
10 | remove_created_on_close: false
11 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import usb
3 |
4 |
5 | def pytest_runtest_call(item):
6 | try:
7 | item.runtest()
8 | except FileNotFoundError:
9 | pytest.skip("dutlink not available") # ty: ignore[call-non-callable]
10 | except usb.core.USBError:
11 | pytest.skip("USB not available") # ty: ignore[call-non-callable]
12 | except usb.core.NoBackendError:
13 | pytest.skip("No USB backend") # ty: ignore[call-non-callable]
14 |
--------------------------------------------------------------------------------
/docs/source/reference/index.md:
--------------------------------------------------------------------------------
1 | # Reference
2 |
3 | This section provides reference documentation for Jumpstarter. The documentation
4 | covers:
5 |
6 | - [API Pages](man-pages/index.md): Command-line tools and utilities
7 | documentation
8 | - [Packages](package-apis/index.md): API documentation for Jumpstarter packages
9 | and components
10 |
11 | These references are useful for developers working with Jumpstarter.
12 |
13 | ```{toctree}
14 | :maxdepth: 1
15 | :hidden:
16 |
17 | man-pages/index.md
18 | package-apis/index.md
19 | ```
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/rcar_s4/overlay/etc/network/if-pre-up.d/wait-carrier.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | IF_WAIT_DELAY=30
4 |
5 | if [ "${IFACE}" != "lo" ]; then
6 | ip link set ${IFACE} up
7 | printf "Waiting for interface %s carrier" "${IFACE}"
8 | while [ ${IF_WAIT_DELAY} -gt 0 ]; do
9 | if [ "$(cat /sys/class/net/${IFACE}/carrier)" = "1" ]; then
10 | printf "\n"
11 | exit 0
12 | fi
13 | sleep 1
14 | printf "."
15 | : $((IF_WAIT_DELAY -= 1))
16 | done
17 | printf " timeout!\n"
18 | exit 1
19 | fi
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from .driver import Opendal
4 | from jumpstarter.common.utils import serve
5 |
6 |
7 | @pytest.fixture
8 | def opendal(tmp_path):
9 | with serve(Opendal(scheme="fs", kwargs={"root": str(tmp_path)})) as client:
10 | yield client
11 |
12 |
13 | @pytest.fixture(autouse=True)
14 | def opendal_namespace(doctest_namespace, opendal, tmp_path):
15 | doctest_namespace["opendal"] = opendal
16 | doctest_namespace["tmp"] = tmp_path
17 |
--------------------------------------------------------------------------------
/docs/source/_templates/page.html:
--------------------------------------------------------------------------------
1 | {% extends "!page.html" %}
2 | {% block extrahead %}
3 | {% include "head.html" %}
4 | {% endblock %}
5 |
6 | {% block content %}
7 | {% if pagename != 'index' %}
8 |
9 |
Warning
10 |
This documentation is actively being updated as the project evolves and may not be complete in all areas.
11 |
12 | {% endif %}
13 |
14 | {{ super() }}
15 | {% endblock %}
16 |
17 | {% block footer %}
18 | {% include "footer.html" %}
19 | {% endblock %}
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/overlay/etc/network/if-pre-up.d/wait-carrier.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | IF_WAIT_DELAY=30
4 |
5 | if [ "${IFACE}" != "lo" ]; then
6 | ip link set ${IFACE} up
7 | printf "Waiting for interface %s carrier" "${IFACE}"
8 | while [ ${IF_WAIT_DELAY} -gt 0 ]; do
9 | if [ "$(cat /sys/class/net/${IFACE}/carrier)" = "1" ]; then
10 | printf "\n"
11 | exit 0
12 | fi
13 | sleep 1
14 | printf "."
15 | : $((IF_WAIT_DELAY -= 1))
16 | done
17 | printf " timeout!\n"
18 | exit 1
19 | fi
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-uboot/jumpstarter_driver_uboot/common.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel
2 |
3 | ESC = "\x1b"
4 |
5 |
6 | class DhcpInfo(BaseModel):
7 | ip_address: str
8 | gateway: str
9 | netmask: str
10 |
11 | @property
12 | def cidr(self) -> str:
13 | try:
14 | octets = [int(x) for x in self.netmask.split(".")]
15 | binary = "".join([bin(x)[2:].zfill(8) for x in octets])
16 | return str(binary.count("1"))
17 | except Exception:
18 | return "24"
19 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver_test.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from jumpstarter_driver_ustreamer.driver import UStreamer
4 |
5 | from jumpstarter.common.utils import serve
6 |
7 |
8 | def test_drivers_video_ustreamer():
9 | try:
10 | instance = UStreamer()
11 | except FileNotFoundError:
12 | pytest.skip("ustreamer not available") # ty: ignore[call-non-callable]
13 |
14 | with serve(instance) as client:
15 | assert client.state().ok
16 | _ = client.snapshot()
17 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/index.md:
--------------------------------------------------------------------------------
1 | # Package APIs
2 |
3 | This section provides reference documentation for Jumpstarter's package APIs and
4 | components. The documentation covers:
5 |
6 | - [Drivers](drivers/index.md): APIs for various driver categories
7 | - [Exceptions](exceptions.md): Exceptions raised by driver clients
8 |
9 | These references are useful for developers extending Jumpstarter or integrating
10 | with custom hardware.
11 |
12 | ```{toctree}
13 | :maxdepth: 1
14 | :hidden:
15 | drivers/index.md
16 | exceptions.md
17 | ```
18 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/__init__.py:
--------------------------------------------------------------------------------
1 | import click
2 | from jumpstarter_cli_common.alias import AliasedGroup
3 | from jumpstarter_cli_common.opt import opt_log_level
4 | from jumpstarter_cli_common.version import version
5 |
6 | from .driver import list_drivers
7 |
8 |
9 | @click.group(cls=AliasedGroup)
10 | @opt_log_level
11 | def driver():
12 | """Jumpstarter driver CLI tool"""
13 |
14 |
15 | driver.add_command(list_drivers)
16 | driver.add_command(version)
17 |
18 | if __name__ == "__main__":
19 | driver()
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import usb
3 |
4 |
5 | def pytest_runtest_call(item):
6 | try:
7 | item.runtest()
8 | except FileNotFoundError:
9 | pytest.skip("yepkit not available") # ty: ignore[call-non-callable]
10 | except usb.core.USBError:
11 | pytest.skip("USB not available, could need root permissions") # ty: ignore[call-non-callable]
12 | except usb.core.NoBackendError:
13 | pytest.skip("No USB backend") # ty: ignore[call-non-callable]
14 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-gpiod/example/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | name: shell-exporter
5 | namespace: default
6 | export:
7 | gpio:
8 | type: jumpstarter_driver_gpiod.driver.DigitalOutput
9 | config:
10 | line: 23
11 | drive: open_drain
12 | bias: pull_up
13 | initial_value: "off"
14 |
15 | gpioin:
16 | type: jumpstarter_driver_gpiod.driver.DigitalInput
17 | config:
18 | line: 24
19 | bias: pull_up
20 | active_low: True
21 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ssh/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | ssh:
10 | type: jumpstarter_driver_ssh.driver.SSHWrapper
11 | config:
12 | default_username: "core"
13 | children:
14 | tcp:
15 | type: jumpstarter_driver_network.driver.TcpNetwork
16 | config:
17 | host: "192.168.1.3"
18 | port: 22
19 |
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/json.py:
--------------------------------------------------------------------------------
1 | import yaml
2 | from pydantic import BaseModel, ConfigDict
3 |
4 |
5 | class JsonBaseModel(BaseModel):
6 | """A Pydantic BaseModel with additional Jumpstarter JSON options applied."""
7 |
8 | def dump_json(self):
9 | return self.model_dump_json(indent=4, by_alias=True)
10 |
11 | def dump_yaml(self):
12 | return yaml.safe_dump(self.model_dump(mode="json", by_alias=True), indent=2)
13 |
14 | model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)
15 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/config/common.py:
--------------------------------------------------------------------------------
1 | from os import getenv
2 | from pathlib import Path
3 |
4 | from pydantic_settings import BaseSettings, SettingsConfigDict
5 | from xdg_base_dirs import xdg_config_home
6 |
7 | from .env import JMP_CLIENT_CONFIG_HOME
8 |
9 | CONFIG_API_VERSION = "jumpstarter.dev/v1alpha1"
10 | CONFIG_PATH = Path(getenv(JMP_CLIENT_CONFIG_HOME, xdg_config_home() / "jumpstarter"))
11 |
12 |
13 | class ObjectMeta(BaseSettings):
14 | model_config = SettingsConfigDict(env_prefix="JMP_")
15 |
16 | namespace: str | None
17 | name: str
18 |
--------------------------------------------------------------------------------
/.github/workflows/e2e.yaml:
--------------------------------------------------------------------------------
1 | name: "Run E2E Tests"
2 | on:
3 | workflow_dispatch:
4 | push:
5 | branches:
6 | - main
7 | - release-*
8 | pull_request:
9 | merge_group:
10 |
11 | permissions:
12 | contents: read
13 |
14 | jobs:
15 | e2e:
16 | if: github.repository_owner == 'jumpstarter-dev'
17 | runs-on: ubuntu-latest
18 | timeout-minutes: 60
19 | continue-on-error: false
20 | steps:
21 | - uses: jumpstarter-dev/jumpstarter-e2e@main
22 | with:
23 | controller-ref: main
24 | jumpstarter-ref: ${{ github.ref }}
25 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/rcar_s4/build_flasher.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | dnf install --setopt=install_weak_deps=false -y git make gcc gcc-c++ which file diffutils wget cpio rsync bc lzop zip patch perl tar qemu-system-aarch64 qemu-img unzboot uboot-tools kmod awk
4 |
5 | git clone --depth 1 --branch 2025.05 https://github.com/buildroot/buildroot /buildroot
6 |
7 | ./replace_kernel.sh
8 | cp -R overlay /buildroot
9 | cp rootfs_only_defconfig /buildroot/configs/
10 | ( cd /buildroot; make rootfs_only_defconfig && make )
11 | mkimage -f flasher.its data/flasher.itb
12 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-http-power/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: ""
7 | token: ""
8 | export:
9 | power:
10 | type: jumpstarter_driver_http_power.driver.HttpPower
11 | config:
12 | name: "splug"
13 | power_on:
14 | url: "http://192.168.1.65/relay/0?turn=on"
15 | power_off:
16 | url: "http://192.168.1.65/relay/0?turn=off"
17 | auth:
18 | basic:
19 | user: admin
20 | password: something
21 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tftp/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | serial:
10 | type: "jumpstarter_driver_pyserial.driver.PySerial"
11 | config:
12 | url: "/dev/ttyUSB0"
13 | baudrate: 1843200
14 | tftp:
15 | type: jumpstarter_driver_tftp.driver.TftpServer
16 | config:
17 | root_dir: "/var/lib/tftpboot/"
18 | host: "192.168.1.111"
19 | port: 6969
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/jumpstarter_protocol/__init__.py:
--------------------------------------------------------------------------------
1 | from .jumpstarter.client.v1 import (
2 | client_pb2,
3 | client_pb2_grpc,
4 | )
5 |
6 | from .jumpstarter.v1 import (
7 | jumpstarter_pb2,
8 | jumpstarter_pb2_grpc,
9 | kubernetes_pb2,
10 | kubernetes_pb2_grpc,
11 | router_pb2,
12 | router_pb2_grpc,
13 | )
14 |
15 | __all__ = [
16 | "client_pb2",
17 | "client_pb2_grpc",
18 | "jumpstarter_pb2",
19 | "jumpstarter_pb2_grpc",
20 | "kubernetes_pb2",
21 | "kubernetes_pb2_grpc",
22 | "router_pb2",
23 | "router_pb2_grpc"
24 | ]
25 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ble/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | ble:
10 | type: "jumpstarter_driver_ble.driver.BleWriteNotifyStream"
11 | config:
12 | address: "00:11:22:33:44:55"
13 | service_uuid: "0000180a-0000-1000-8000-000000000000"
14 | write_char_uuid: "0000fe41-8e22-4541-9d4c-000000000000"
15 | notify_char_uuid: "0000fe42-8e22-4541-9d4c-000000000000"
16 |
17 |
18 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-shell/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | name: shell-exporter
5 | namespace: default
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | example:
10 | type: jumpstarter_driver_shell.driver.Shell
11 | config:
12 | methods:
13 | ls: "ls"
14 | method2: "echo 'Hello World 2'"
15 | #multi line method
16 | method3: |
17 | echo 'Hello World $1'
18 | echo 'Hello World $2'
19 | env_var: "echo $ENV_VAR"
20 |
21 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-composite/README.md:
--------------------------------------------------------------------------------
1 | # Composite Driver
2 |
3 | `jumpstarter-driver-composite` provides functionality for interacting with composite devices.
4 |
5 | ## Installation
6 |
7 | ```bash
8 | pip3 install --extra-index-url https://pkg.jumpstarter.dev/simple/ jumpstarter-driver-composite
9 | ```
10 |
11 | ## Configuration
12 |
13 | Example configuration:
14 |
15 | ```yaml
16 | export:
17 | composite:
18 | type: jumpstarter_driver_composite.driver.Composite
19 | config:
20 | # Add required config parameters here
21 | ```
22 |
23 | ## API Reference
24 |
25 | Add API documentation here.
26 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-qemu/README.md:
--------------------------------------------------------------------------------
1 | # QEMU driver
2 |
3 | `jumpstarter-driver-qemu` provides functionality for interacting with QEMU
4 | virtualization platform.
5 |
6 | ## Installation
7 |
8 | ```{code-block} console
9 | :substitutions:
10 | $ pip3 install --extra-index-url {{index_url}} jumpstarter-driver-qemu
11 | ```
12 |
13 | ## Configuration
14 |
15 | Example configuration:
16 |
17 | ```yaml
18 | export:
19 | qemu:
20 | type: jumpstarter_driver_qemu.driver.Qemu
21 | config:
22 | # Add required config parameters here
23 | ```
24 |
25 | ## API Reference
26 |
27 | Add API documentation here.
28 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/common/importlib_test.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from .importlib import import_class
4 |
5 |
6 | def test_import_class():
7 | import_class("os.open", [], True)
8 |
9 | with pytest.raises(ImportError):
10 | import_class("os.invalid", [], True)
11 |
12 | with pytest.raises(ImportError):
13 | import_class("os.open", [], False)
14 |
15 | import_class("os.open", ["os.*"], False)
16 |
17 | with pytest.raises(ImportError):
18 | import_class("os.open", ["sys.*"], False)
19 |
20 | with pytest.raises(ImportError):
21 | import_class("os", [], True)
22 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-dutlink/README.md:
--------------------------------------------------------------------------------
1 | # DUT Link driver
2 |
3 | `jumpstarter-driver-dutlink` provides functionality for interacting with DUT
4 | Link devices.
5 |
6 | ## Installation
7 |
8 | ```{code-block} console
9 | :substitutions:
10 | $ pip3 install --extra-index-url {{index_url}} jumpstarter-driver-dutlink
11 | ```
12 |
13 | ## Configuration
14 |
15 | Example configuration:
16 |
17 | ```yaml
18 | export:
19 | dutlink:
20 | type: jumpstarter_driver_dutlink.driver.Dutlink
21 | config:
22 | # Add required config parameters here
23 | ```
24 |
25 | ## API Reference
26 |
27 | Add API documentation here.
28 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/examples/exporter.yml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | # endpoint and token are intentionally left empty
4 | metadata:
5 | namespace: default
6 | name: corellium-demo
7 | endpoint: ""
8 | token: ""
9 | export:
10 | rd1ae:
11 | type: jumpstarter_driver_corellium.driver.Corellium
12 | config:
13 | project_id: "778f00af-5e9b-40e6-8e7f-c4f14b632e9c"
14 | device_name: "jmp-rd1ae"
15 | device_flavor: "kronos"
16 | # optional
17 | device_os: "1.1.1"
18 | device_build: "Critical Application Monitor (Baremetal)"
19 | console_name: "Primary Compute Non-Secure"
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/pexpect.py:
--------------------------------------------------------------------------------
1 | import socket
2 | from contextlib import contextmanager
3 |
4 | from pexpect.fdpexpect import fdspawn
5 |
6 | from .portforward import TcpPortforwardAdapter
7 | from jumpstarter.client import DriverClient
8 |
9 |
10 | @contextmanager
11 | def PexpectAdapter(*, client: DriverClient, method: str = "connect"):
12 | with TcpPortforwardAdapter(client=client, method=method) as addr:
13 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
14 | sock.connect(addr)
15 |
16 | try:
17 | yield fdspawn(sock)
18 | finally:
19 | sock.close()
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/rcar_s4/rootfs_only_defconfig:
--------------------------------------------------------------------------------
1 | BR2_aarch64=y
2 | BR2_TOOLCHAIN_EXTERNAL=y
3 | BR2_TARGET_GENERIC_HOSTNAME="flasher"
4 | BR2_TARGET_GENERIC_ISSUE="flasher"
5 | BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
6 | BR2_TARGET_GENERIC_ROOT_PASSWD=""
7 | BR2_SYSTEM_DHCP="eth0"
8 | BR2_ROOTFS_OVERLAY="$(CONFIG_DIR)/overlay"
9 | BR2_PACKAGE_CA_CERTIFICATES=y
10 | BR2_PACKAGE_OPENSSL=y
11 | BR2_PACKAGE_LIBCURL=y
12 | BR2_PACKAGE_LIBCURL_CURL=y
13 | BR2_PACKAGE_NTP=y
14 | BR2_PACKAGE_NTP_SNTP=y
15 | BR2_PACKAGE_NTP_NTPDATE=y
16 | BR2_TARGET_ROOTFS_CPIO=y
17 | BR2_TARGET_ROOTFS_CPIO_LZO=y
18 | BR2_PACKAGE_DROPBEAR=n
19 | # BR2_TARGET_ROOTFS_TAR is not set
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from anyio.from_thread import start_blocking_portal
3 |
4 | from jumpstarter.common import TemporaryTcpListener
5 |
6 |
7 | async def echo_handler(stream):
8 | async with stream:
9 | while True:
10 | try:
11 | await stream.send(await stream.receive())
12 | except Exception:
13 | pass
14 |
15 |
16 | @pytest.fixture
17 | def tcp_echo_server():
18 | with start_blocking_portal() as portal:
19 | with portal.wrap_async_context_manager(TemporaryTcpListener(echo_handler, local_host="127.0.0.1")) as addr:
20 | yield addr
21 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-vnc/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | vnc:
10 | type: jumpstarter_driver_vnc.driver.Vnc
11 | # You can set the default encryption behavior for the `j vnc session` command.
12 | # If not set, it defaults to False (unencrypted).
13 | default_encrypt: false
14 | children:
15 | tcp:
16 | type: jumpstarter_driver_network.driver.TcpNetwork
17 | config:
18 | host: "127.0.0.1"
19 | port: 5901 # Default VNC port for display :1
20 |
--------------------------------------------------------------------------------
/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/serialize.py:
--------------------------------------------------------------------------------
1 | from typing import Annotated, Any, Dict
2 |
3 | from kubernetes_asyncio.client.models import V1Condition, V1ObjectMeta, V1ObjectReference
4 | from pydantic import WrapSerializer
5 |
6 |
7 | def k8s_obj_to_dict(value: Any, handler, info) -> Dict[str, Any]:
8 | result = value.to_dict(serialize=True)
9 | return {k: v for k, v in result.items() if v is not None}
10 |
11 |
12 | SerializeV1Condition = Annotated[V1Condition, WrapSerializer(k8s_obj_to_dict)]
13 | SerializeV1ObjectMeta = Annotated[V1ObjectMeta, WrapSerializer(k8s_obj_to_dict)]
14 | SerializeV1ObjectReference = Annotated[V1ObjectReference, WrapSerializer(k8s_obj_to_dict)]
15 |
--------------------------------------------------------------------------------
/docs/source/reference/man-pages/j.md:
--------------------------------------------------------------------------------
1 | # j
2 |
3 | The `j` command is available within the Jumpstarter shell environment (launched
4 | via `jmp shell`). It provides access to driver CLI interfaces configured in your
5 | exporter.
6 |
7 | Usage:
8 |
9 | ```console
10 | $ j [OPTIONS] COMMAND [ARGS]...
11 | ```
12 |
13 | The available commands depend on which drivers are loaded in your current
14 | session. When you run the `j` command in the shell:
15 |
16 | - Use `j` alone to see all available driver interfaces
17 | - Access specific drivers with `j `
18 | - Each driver exposes different commands through this interface
19 |
20 | Available commands vary depending on your configured drivers.
21 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/__init__.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 |
4 | def configure_grpc_env():
5 | # disable informative logs by default, i.e.:
6 | # WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
7 | # I0000 00:00:1739970744.889307 61962 ssl_transport_security.cc:1665] Handshake failed ...
8 | if os.environ.get("GRPC_VERBOSITY") is None:
9 | os.environ["GRPC_VERBOSITY"] = "ERROR"
10 | if os.environ.get("GLOG_minloglevel") is None:
11 | os.environ["GLOG_minloglevel"] = "2"
12 |
13 |
14 | # make sure that the grpc environment is always configured
15 | # before any grpc calls are made to avoid unnecessary logs
16 | configure_grpc_env()
17 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-power/README.md:
--------------------------------------------------------------------------------
1 | # Power driver
2 |
3 | `jumpstarter-driver-power` provides functionality for interacting with power
4 | control devices.
5 |
6 | ## Installation
7 |
8 | ```{code-block} console
9 | :substitutions:
10 | $ pip3 install --extra-index-url {{index_url}} jumpstarter-driver-power
11 | ```
12 |
13 | ## Configuration
14 |
15 | Example configuration:
16 |
17 | ```yaml
18 | export:
19 | power:
20 | type: jumpstarter_driver_power.driver.MockPower
21 | config:
22 | # Add required config parameters here
23 | ```
24 |
25 | ## API Reference
26 |
27 | ```{eval-rst}
28 | .. autoclass:: jumpstarter_driver_power.client.PowerClient()
29 | :members: on, off, read, cycle
30 | ```
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-yepkit/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | name: exporter
5 | namespace: default
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | power:
10 | type: jumpstarter_driver_yepkit.driver.Ykush
11 | config:
12 | port: "1"
13 |
14 | power2:
15 | type: jumpstarter_driver_yepkit.driver.Ykush
16 | config:
17 | serial: "YK25838"
18 | port: "2"
19 |
20 | power3:
21 | type: jumpstarter_driver_yepkit.driver.Ykush
22 | config:
23 | port: "3"
24 |
25 | all:
26 | type: jumpstarter_driver_yepkit.driver.Ykush
27 | config:
28 | port: "all"
29 |
30 |
--------------------------------------------------------------------------------
/docs/source/reference/package-apis/drivers/uboot.yaml:
--------------------------------------------------------------------------------
1 | type: "jumpstarter_driver_uboot.driver.UbootConsole"
2 | children:
3 | power:
4 | type: "jumpstarter_driver_power.driver.MockPower"
5 | config: {} # omitted, power driver configuration
6 | serial:
7 | type: "jumpstarter_driver_pyserial.driver.PySerial"
8 | config: # omitted, serial driver configuration
9 | url: "loop://"
10 | # instead of configuring the power and serial driver inline
11 | # other drivers configured on the exporter can also be referenced
12 | # power:
13 | # ref: "dutlink.power"
14 | # serial:
15 | # ref: "dutlink.console"
16 | config:
17 | prompt: "=>" # the u-boot command prompt to expect, defaults to "=>"
18 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-power/jumpstarter_driver_power/client_test.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import time
3 | from unittest.mock import MagicMock
4 |
5 | from .driver import MockPower
6 | from jumpstarter.common.utils import serve
7 |
8 |
9 | def test_log_stream(monkeypatch):
10 | with serve(MockPower()) as client:
11 | log = MagicMock()
12 | monkeypatch.setattr(client, "_AsyncDriverClient__log", log)
13 | with client.log_stream():
14 | client.on()
15 | time.sleep(1) # to ensure log is flushed
16 | log.assert_called_with(logging.INFO, "power on")
17 |
18 | client.off()
19 | time.sleep(1)
20 | log.assert_called_with(logging.INFO, "power off")
21 |
--------------------------------------------------------------------------------
/packages/hatch-pin-jumpstarter/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "hatch-pin-jumpstarter"
3 | version = "0.1.0"
4 | description = "Hatch plugin that pins jumpstarter packages in the monorepo"
5 | readme = "README.md"
6 | authors = [
7 | { name = "Nick Cao", email = "nickcao@nichi.co" }
8 | ]
9 | requires-python = ">=3.11"
10 | dependencies = [
11 | "hatchling>=1.27.0",
12 | "packaging>=24.2",
13 | "tomli>=2.2.1",
14 | "tomli-w>=1.2.0",
15 | ]
16 |
17 | [build-system]
18 | requires = ["hatchling"]
19 | build-backend = "hatchling.build"
20 |
21 | [dependency-groups]
22 | dev = [
23 | "pytest>=8.3.5",
24 | "pytest-cov>=6.1.1",
25 | ]
26 |
27 | [project.entry-points.hatch]
28 | pin_jumpstarter = "hatch_pin_jumpstarter"
29 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/common/utils_test.py:
--------------------------------------------------------------------------------
1 | import shutil
2 |
3 | from .utils import launch_shell
4 |
5 |
6 | def test_launch_shell(tmp_path, monkeypatch):
7 | monkeypatch.setenv("SHELL", shutil.which("true"))
8 | exit_code = launch_shell(
9 | host=str(tmp_path / "test.sock"),
10 | context="remote",
11 | allow=["*"],
12 | unsafe=False,
13 | use_profiles=False
14 | )
15 | assert exit_code == 0
16 |
17 | monkeypatch.setenv("SHELL", shutil.which("false"))
18 | exit_code = launch_shell(
19 | host=str(tmp_path / "test.sock"),
20 | context="remote", allow=["*"],
21 | unsafe=False,
22 | use_profiles=False
23 | )
24 | assert exit_code == 1
25 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tmt/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | tmt:
10 | type: jumpstarter_driver_tmt.driver.TMT
11 | config:
12 | reboot_cmd: "j power cycle"
13 | default_username: "root"
14 | default_password: "somePass"
15 | children:
16 | ssh:
17 | ref: ssh
18 | ssh:
19 | type: jumpstarter_driver_network.driver.TcpNetwork
20 | config:
21 | host: 127.0.0.1
22 | port: 2222
23 | enable_address: true
24 | power:
25 | type: jumpstarter_driver_power.driver.MockPower
26 |
27 |
28 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/config/grpc.py:
--------------------------------------------------------------------------------
1 | import grpc
2 |
3 | from .common import ObjectMeta
4 |
5 |
6 | def call_credentials(kind: str, metadata: ObjectMeta, token: str):
7 | def metadata_call_credentials(context: grpc.AuthMetadataContext, callback: grpc.AuthMetadataPluginCallback):
8 | callback(
9 | [
10 | ("jumpstarter-kind", kind),
11 | ("jumpstarter-namespace", metadata.namespace),
12 | ("jumpstarter-name", metadata.name),
13 | ],
14 | None,
15 | )
16 |
17 | return grpc.composite_call_credentials(
18 | grpc.metadata_call_credentials(metadata_call_credentials),
19 | grpc.access_token_call_credentials(token),
20 | )
21 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/rcar_s4/manifest.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: FlashBundleManifest
3 | metadata:
4 | name: rcar-s4
5 | spec:
6 | manufacturer: Renesas
7 | link: "https://www.renesas.com/en/products/automotive-products/automotive-system-chips-socs/r-car-s4-automotive-system-chip-soc-car-servercommunication-gateway"
8 | # boot default configuration R-Car S4 Spider, for S4SK use "bootm 0x58000000#s4sk"
9 | bootcmd: "bootm 0x58000000"
10 | shelltype: "busybox"
11 | login:
12 | login_prompt: "login:"
13 | username: "root"
14 | prompt: "#"
15 | default_target: "emmc"
16 | targets:
17 | emmc: "/dev/mmcblk0"
18 | kernel:
19 | file: data/flasher.itb
20 | address: "0x58000000"
21 |
--------------------------------------------------------------------------------
/docs/source/getting-started/index.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | This section provides hands-on guides to start using Jumpstarter in your own
4 | environment. The guides cover:
5 |
6 | - [Installation](installation/index.md): Setting up Jumpstarter packages and
7 | services
8 | - [Configuration](configuration/index.md): Configuring clients, exporters, and
9 | authentication
10 | - [Guides](guides/index.md): Running your first tests and integrating with your
11 | development workflow
12 |
13 | These guides support both local-mode for individual development and
14 | distributed-mode for team environments with shared hardware resources.
15 |
16 | ```{toctree}
17 | :maxdepth: 1
18 | :hidden:
19 | installation/index.md
20 | configuration/index.md
21 | guides/index.md
22 | ```
--------------------------------------------------------------------------------
/examples/soc-pytest/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-example-soc-pytest"
3 | version = "0.1.0"
4 | description = ""
5 | authors = [
6 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
7 | { name = "Kirk Brauer", email = "kbrauer@hatci.com" },
8 | { name = "Nick Cao", email = "ncao@redhat.com" },
9 | ]
10 | readme = "README.md"
11 | license = "Apache-2.0"
12 | requires-python = ">=3.11"
13 | dependencies = [
14 | "pytest>=8.3.2",
15 | "jumpstarter",
16 | "jumpstarter-testing",
17 | "jumpstarter-imagehash",
18 | "jumpstarter-driver-network",
19 | "jumpstarter-driver-dutlink",
20 | ]
21 |
22 | [tool.pytest.ini_options]
23 | addopts = "-s --ignore examples/pytest/test_on_rpi4.py"
24 | log_cli = 1
25 | log_cli_level = "INFO"
26 |
--------------------------------------------------------------------------------
/.devfile/Containerfile:
--------------------------------------------------------------------------------
1 | FROM quay.io/devfile/base-developer-image:ubi9-latest
2 | LABEL maintainer="Jumpstarter.dev"
3 |
4 | LABEL name="devfile/udi9/jumpstarter"
5 |
6 | #labels for container catalog
7 | LABEL summary="devfile jumpstarter developer image"
8 | LABEL description="Image with developers tools."
9 | LABEL io.k8s.display-name="jumpstarter-developer-universal"
10 |
11 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
12 | COPY --from=ghcr.io/astral-sh/uv:latest /uvx /bin/uvx
13 |
14 | USER root
15 |
16 | RUN dnf -y install make git python3.12 libusbx python3-pyusb golang podman && dnf clean all
17 |
18 | USER 10001
19 |
20 | # This will make sure that we always run python from our venv instead
21 | RUN echo "alias python='uv run python'" >> /home/user/.bashrc
22 |
--------------------------------------------------------------------------------
/docs/source/getting-started/configuration/index.md:
--------------------------------------------------------------------------------
1 | # Configuration
2 |
3 | This section explains how to configure Jumpstarter for your environment.
4 |
5 | - [Files](files.md): Understanding the structure and content of configuration
6 | files
7 | - [Loading Order](loading-order.md): Understanding how configuration files are
8 | prioritized from different sources (environment variables, command line,
9 | system and user config files)
10 | - [Authentication](authentication.md): Setting up OIDC and managing tokens
11 |
12 | For a list of supported configuration options including an explanation please
13 | refer to the [MAN pages](../../reference/man-pages/index.md).
14 |
15 | ```{toctree}
16 | :maxdepth: 1
17 | :hidden:
18 | files.md
19 | loading-order.md
20 | authentication.md
21 | ```
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/build_bundle.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # oras login quay.io -u mangelajo
4 |
5 | set -e
6 |
7 | FLASHER_OCI_CONTAINER="${1:-quay.io/jumpstarter-dev/jumpstarter-flasher-test:latest}"
8 | BUNDLE_FILES=${2:-"./test/"}
9 |
10 | echo "Building and pushing ${FLASHER_OCI_CONTAINER}"
11 |
12 | set -x
13 |
14 | cd "${BUNDLE_FILES}"
15 | MANIFESTS=
16 | for file in $(ls -1 *.yaml); do
17 | MANIFESTS="${MANIFESTS} ${file}:application/yaml "
18 | done
19 | DATA_FILES=
20 | for file in $(find ./data -type f -prune -a -not -name .gitkeep); do
21 | DATA_FILES="${DATA_FILES} ${file}:application/octet-stream "
22 | done
23 |
24 | oras push $FLASHER_OCI_CONTAINER \
25 | --artifact-type application/vnd.oci.bundle.v1 \
26 | $MANIFESTS \
27 | $DATA_FILES
28 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM --platform=$BUILDPLATFORM ghcr.io/astral-sh/uv:latest AS uv
2 |
3 | FROM --platform=$BUILDPLATFORM fedora:42 AS builder
4 | RUN dnf install -y make git && \
5 | dnf clean all && \
6 | rm -rf /var/cache/dnf
7 | COPY --from=uv /uv /uvx /bin/
8 |
9 | FROM fedora:42 AS product
10 | RUN dnf install -y python3 ustreamer libusb1 android-tools python3-libgpiod && \
11 | dnf clean all && \
12 | rm -rf /var/cache/dnf
13 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
14 |
15 | FROM builder AS wheels
16 | ADD . /src
17 | RUN make -C /src build
18 |
19 | FROM product
20 | RUN --mount=from=wheels,source=/src/dist,target=/dist \
21 | uv venv /jumpstarter && \
22 | VIRTUAL_ENV=/jumpstarter uv pip install /dist/*.whl
23 | ENV PATH="/jumpstarter/bin:$PATH"
24 |
--------------------------------------------------------------------------------
/kind_config.yaml:
--------------------------------------------------------------------------------
1 | kind: Cluster
2 | apiVersion: kind.x-k8s.io/v1alpha4
3 | kubeadmConfigPatches:
4 | - |
5 | kind: ClusterConfiguration
6 | apiServer:
7 | extraArgs:
8 | "service-node-port-range": "3000-32767"
9 | - |
10 | kind: InitConfiguration
11 | nodeRegistration:
12 | kubeletExtraArgs:
13 | node-labels: "ingress-ready=true"
14 | nodes:
15 | - role: control-plane
16 | extraPortMappings:
17 | - containerPort: 80 # ingress controller
18 | hostPort: 5080
19 | protocol: TCP
20 | - containerPort: 30010 # grpc nodeport
21 | hostPort: 8082
22 | protocol: TCP
23 | - containerPort: 30011 # grpc router nodeport
24 | hostPort: 8083
25 | protocol: TCP
26 | - containerPort: 443 # minimalistic UI
27 | hostPort: 5443
28 | protocol: TCP
29 |
--------------------------------------------------------------------------------
/examples/soc-pytest/jumpstarter_example_soc_pytest/image/scripts/prepare-latest-raw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -x
3 | # all output to serial port
4 | sudo sed -i 's/console=serial0,115200 console=tty1/console=serial0,115200/g' mnt/boot/firmware/cmdline.txt
5 | cat mnt/boot/firmware/cmdline.txt
6 |
7 | cat << EOF | sudo tee mnt/boot/firmware/custom.toml
8 | # Raspberry Pi First Boot Setup
9 | [system]
10 | hostname = "rpitest"
11 |
12 | [user]
13 | name = "root"
14 | password = "changeme"
15 | password_encrypted = false
16 |
17 | [ssh]
18 | enabled = false
19 |
20 | [wlan]
21 | country = "es"
22 |
23 | [locale]
24 | keymap = "es"
25 | timezone = "Europe/Madrid"
26 | EOF
27 |
28 | cat << EOF | sudo tee -a mnt/boot/firmware/config.txt
29 | dtparam=spi=on
30 | dtoverlay=tpm-slb9670
31 | enable_uart=1
32 | EOF
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-uboot/jumpstarter_driver_uboot/driver.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 |
3 | from jumpstarter.driver import Driver, export
4 |
5 |
6 | @dataclass(kw_only=True)
7 | class UbootConsole(Driver):
8 | prompt: str = "\n=>"
9 |
10 | @classmethod
11 | def client(cls) -> str:
12 | return "jumpstarter_driver_uboot.client.UbootConsoleClient"
13 |
14 | def __post_init__(self):
15 | if hasattr(super(), "__post_init__"):
16 | super().__post_init__()
17 |
18 | for child in ("power", "serial"):
19 | if child not in self.children:
20 | raise ValueError("UbootConsole: {} driver not configured as a child".format(child))
21 |
22 | @export
23 | def get_prompt(self) -> str:
24 | return self.prompt
25 |
--------------------------------------------------------------------------------
/docs/source/getting-started/guides/index.md:
--------------------------------------------------------------------------------
1 | # Guides
2 |
3 | This section provides guidance on how to use Jumpstarter effectively in your
4 | development workflow. The guides cover:
5 |
6 | - [Setup Local Mode](setup-local-mode.md): Running Jumpstarter in local mode for
7 | individual development
8 | - [Setup Distributed Mode](setup-distributed-mode.md): Configuring Jumpstarter
9 | for team environments with shared resources
10 | - [Examples](examples.md): Practical examples of Jumpstarter usage in common
11 | scenarios
12 | - [Integration Patterns](integration-patterns.md): Integrate Jumpstarter into
13 | your existing workflows and systems
14 |
15 |
16 | ```{toctree}
17 | :maxdepth: 1
18 | :hidden:
19 | setup-local-mode.md
20 | setup-distributed-mode.md
21 | examples.md
22 | integration-patterns.md
23 | ```
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-common/jumpstarter_cli_common/signal.py:
--------------------------------------------------------------------------------
1 | import signal
2 |
3 | import click
4 | from anyio import open_signal_receiver
5 | from anyio.abc import CancelScope
6 |
7 |
8 | # Reference: https://github.com/agronholm/anyio/blob/4.9.0/docs/signals.rst
9 | async def signal_handler(scope: CancelScope):
10 | with open_signal_receiver(signal.SIGINT, signal.SIGTERM) as signals:
11 | async for signum in signals:
12 | match signum:
13 | case signal.SIGINT:
14 | click.echo("SIGINT pressed, terminating", err=True)
15 | case signal.SIGTERM:
16 | click.echo("SIGTERM received, terminating", err=True)
17 | case _:
18 | pass
19 |
20 | scope.cancel()
21 |
22 | break
23 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver_test.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import usb
3 |
4 | from jumpstarter_driver_sdwire.driver import SDWire
5 |
6 | from jumpstarter.common.utils import serve
7 |
8 |
9 | def test_drivers_sdwire():
10 | try:
11 | instance = SDWire()
12 | except FileNotFoundError:
13 | pytest.skip("sd-wire not available") # ty: ignore[call-non-callable]
14 | except usb.core.USBError:
15 | pytest.skip("USB not available") # ty: ignore[call-non-callable]
16 | except usb.core.NoBackendError:
17 | pytest.skip("No USB backend") # ty: ignore[call-non-callable]
18 |
19 | with serve(instance) as client:
20 | client.host()
21 | assert instance.query() == "host"
22 | client.dut()
23 | assert instance.query() == "dut"
24 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/exporter/logging.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from collections import deque
3 |
4 | from jumpstarter_protocol import jumpstarter_pb2
5 |
6 |
7 | class LogHandler(logging.Handler):
8 | def __init__(self, queue: deque):
9 | logging.Handler.__init__(self)
10 | self.queue = queue
11 | self.listener = None
12 |
13 | def enqueue(self, record):
14 | self.queue.append(record)
15 |
16 | def prepare(self, record):
17 | return jumpstarter_pb2.LogStreamResponse(
18 | uuid="",
19 | severity=record.levelname,
20 | message=self.format(record),
21 | )
22 |
23 | def emit(self, record):
24 | try:
25 | self.enqueue(self.prepare(record))
26 | except Exception:
27 | self.handleError(record)
28 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 |
3 | from jumpstarter_driver_power.client import PowerClient
4 |
5 | from jumpstarter.client.decorators import driver_click_group
6 |
7 |
8 | @dataclass(kw_only=True)
9 | class SNMPServerClient(PowerClient):
10 | """Client interface for SNMP Power Control"""
11 |
12 | def on(self):
13 | """Turn power on"""
14 | self.call("on")
15 |
16 | def off(self):
17 | """Turn power off"""
18 | self.call("off")
19 |
20 | def cli(self):
21 | @driver_click_group(self)
22 | def snmp():
23 | """SNMP power control commands"""
24 | pass
25 |
26 | for cmd in super().cli().commands.values():
27 | snmp.add_command(cmd)
28 |
29 | return snmp
30 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/common/resources.py:
--------------------------------------------------------------------------------
1 | from typing import Annotated, Literal, Union
2 | from uuid import UUID
3 |
4 | from pydantic import BaseModel, Field, Json
5 |
6 |
7 | class ClientStreamResource(BaseModel):
8 | kind: Literal["client_stream"] = "client_stream"
9 | uuid: UUID
10 | x_jmp_content_encoding: str | None = None
11 |
12 |
13 | class PresignedRequestResource(BaseModel):
14 | kind: Literal["presigned_request"] = "presigned_request"
15 | headers: dict[str, str]
16 | url: str
17 | method: Literal["GET", "PUT"]
18 |
19 |
20 | Resource = Annotated[
21 | Union[ClientStreamResource, PresignedRequestResource],
22 | Field(discriminator="kind"),
23 | ]
24 |
25 |
26 | class ResourceMetadata(BaseModel):
27 | resource: Json[Resource]
28 | x_jmp_accept_encoding: str | None = None
29 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py:
--------------------------------------------------------------------------------
1 | from importlib.metadata import entry_points
2 |
3 | import click
4 | from rich.console import Console
5 | from rich.table import Table
6 |
7 |
8 | @click.command("list")
9 | def list_drivers():
10 | drivers = list(entry_points(group="jumpstarter.drivers"))
11 | if not drivers:
12 | click.echo("No drivers found.")
13 | else:
14 | table = Table(
15 | box=None,
16 | header_style=None,
17 | pad_edge=None,
18 | )
19 |
20 | table.add_column("NAME", no_wrap=True)
21 | table.add_column("TYPE")
22 |
23 | for driver in drivers:
24 | table.add_row(
25 | driver.name,
26 | driver.value.replace(":", "."),
27 | )
28 |
29 | Console().print(table)
30 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py:
--------------------------------------------------------------------------------
1 | """
2 | Corellium API types.
3 | """
4 | from dataclasses import dataclass, field
5 | from typing import Optional
6 |
7 |
8 | @dataclass
9 | class Project:
10 | """
11 | Dataclass that represents a Corellium project.
12 | """
13 | id: str
14 | name: str
15 |
16 |
17 | @dataclass
18 | class Device:
19 | """
20 | Dataclass to represent a Corellium Device.
21 |
22 | A device object is used to create virtual instances.
23 | """
24 | name: str
25 | type: str
26 | flavor: str
27 | description: str
28 | model: str
29 | peripherals: bool
30 | quotas: dict
31 |
32 |
33 | @dataclass
34 | class Instance:
35 | """
36 | Virtual instance dataclass.
37 | """
38 | id: str
39 | state: Optional[str] = field(default=None)
40 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/streams/aiohttp.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 |
3 | from aiohttp import ClientError, StreamReader
4 | from anyio import BrokenResourceError, EndOfStream
5 | from anyio.abc import ObjectStream
6 |
7 |
8 | @dataclass(frozen=True, kw_only=True, slots=True)
9 | class AiohttpStreamReaderStream(ObjectStream[bytes]):
10 | reader: StreamReader
11 |
12 | async def send(self, item: bytes):
13 | raise BrokenResourceError
14 |
15 | async def receive(self) -> bytes:
16 | try:
17 | item = await self.reader.readany()
18 | except ClientError as e:
19 | raise BrokenResourceError from e
20 | if len(item) == 0:
21 | raise EndOfStream
22 | return item
23 |
24 | async def send_eof(self):
25 | pass
26 |
27 | async def aclose(self):
28 | pass
29 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/k8s.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | import click
4 | from kubernetes_asyncio.client.exceptions import ApiException
5 | from kubernetes_asyncio.config.config_exception import ConfigException
6 |
7 |
8 | def handle_k8s_api_exception(e: ApiException):
9 | """Handle a Kubernetes API exception"""
10 | # Try to parse the JSON response
11 | try:
12 | json_body = json.loads(e.body)
13 | raise click.ClickException(f"Error from server ({json_body['reason']}): {json_body['message']}") from e
14 | except json.decoder.JSONDecodeError:
15 | raise click.ClickException(f"Server error: {e.body}") from e
16 |
17 |
18 | def handle_k8s_config_exception(e: ConfigException):
19 | """Handle a Kubernetes config exception"""
20 | # Try to parse the JSON response
21 | raise click.ClickException(e.args[0]) from e
22 |
--------------------------------------------------------------------------------
/docs/source/getting-started/installation/service/index.md:
--------------------------------------------------------------------------------
1 | # Service
2 |
3 | This section explains how to install and configure the Jumpstarter service in your Kubernetes cluster. The service enables centralized management of your Jumpstarter environment.
4 |
5 | ## Getting Started
6 |
7 | For most users, we recommend starting with a **local installation** to get familiar with Jumpstarter before moving to production deployments.
8 |
9 | ```{toctree}
10 | :maxdepth: 2
11 |
12 | service-local.md
13 | service-production.md
14 | ```
15 |
16 | ## Quick Start
17 |
18 | **New to Jumpstarter?** Start with the [Local Installation](service-local.md) guide to get up and running quickly on your development machine.
19 |
20 | **Ready for production?** See the [Production Deployment](service-production.md) guide for Kubernetes and OpenShift clusters with proper security, monitoring, and ingress configurations.
21 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.py:
--------------------------------------------------------------------------------
1 | import click
2 | from jumpstarter_cli_common.alias import AliasedGroup
3 | from jumpstarter_cli_common.opt import opt_log_level
4 | from jumpstarter_cli_common.version import version
5 |
6 | from .create import create
7 | from .delete import delete
8 | from .get import get
9 | from .import_res import import_res
10 | from .install import install, ip, uninstall
11 |
12 |
13 | @click.group(cls=AliasedGroup)
14 | @opt_log_level
15 | def admin():
16 | """Jumpstarter Kubernetes cluster admin CLI tool"""
17 |
18 |
19 | admin.add_command(get)
20 | admin.add_command(create)
21 | admin.add_command(delete)
22 | admin.add_command(install)
23 | admin.add_command(uninstall)
24 | admin.add_command(ip)
25 | admin.add_command(import_res)
26 | admin.add_command(version)
27 | admin.add_command(ip)
28 |
29 | if __name__ == "__main__":
30 | admin()
31 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/client.py:
--------------------------------------------------------------------------------
1 | import io
2 | from base64 import b64decode
3 |
4 | from PIL import Image
5 |
6 | from .common import UStreamerState
7 | from jumpstarter.client import DriverClient
8 |
9 |
10 | class UStreamerClient(DriverClient):
11 | """UStreamer client class
12 |
13 | Client methods for the UStreamer driver.
14 | """
15 |
16 | def state(self):
17 | """
18 | Get state of ustreamer service
19 | """
20 |
21 | return UStreamerState.model_validate(self.call("state"))
22 |
23 | def snapshot(self):
24 | """
25 | Get a snapshot image from the video input
26 |
27 | :return: PIL Image object of the snapshot image
28 | :rtype: PIL.Image
29 | """
30 | input_jpg_data = b64decode(self.call("snapshot"))
31 | return Image.open(io.BytesIO(input_jpg_data))
32 |
--------------------------------------------------------------------------------
/__templates__/driver/jumpstarter_driver/driver.py.tmpl:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 |
3 | from jumpstarter.driver import Driver, export
4 |
5 | @dataclass(kw_only=True)
6 | class ${DRIVER_CLASS}(Driver):
7 | """${DRIVE_NAME} driver for Jumpstarter"""
8 |
9 | some_config: str = "default"
10 | some_other_config: int = 69
11 |
12 | def __post_init__(self):
13 | if hasattr(super(), "__post_init__"):
14 | super().__post_init__()
15 | # some initialization here.
16 |
17 | @classmethod
18 | def client(cls) -> str:
19 | return "jumpstarter_driver_${DRIVER_NAME}.client.${DRIVER_CLASS}Client"
20 |
21 | @export
22 | def method1(self):
23 | self.logger.info("Method1 called")
24 | return "method1 response"
25 |
26 | @export
27 | def method2(self):
28 | self.logger.info("Method2 called")
29 | return "method2 response"
30 |
--------------------------------------------------------------------------------
/packages/jumpstarter-testing/jumpstarter_testing/pytest_test.py:
--------------------------------------------------------------------------------
1 | from jumpstarter_driver_power.driver import MockPower
2 | from pytest import Pytester
3 |
4 | from jumpstarter.config.env import JMP_DRIVERS_ALLOW, JUMPSTARTER_HOST
5 | from jumpstarter.exporter import Session
6 |
7 |
8 | def test_env(pytester: Pytester, monkeypatch):
9 | pytester.makepyfile(
10 | """
11 | from jumpstarter_testing import JumpstarterTest
12 |
13 | class TestSample(JumpstarterTest):
14 | def test_simple(self, client):
15 | client.on()
16 | """
17 | )
18 |
19 | with Session(root_device=MockPower()) as session:
20 | with session.serve_unix() as path:
21 | monkeypatch.setenv(JUMPSTARTER_HOST, str(path))
22 | monkeypatch.setenv(JMP_DRIVERS_ALLOW, "UNSAFE")
23 | result = pytester.runpytest()
24 | result.assert_outcomes(passed=1)
25 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "d59db33d-27bd-4b22-878d-49e4758a648e",
4 | "name": "Default Project",
5 | "settings": {
6 | "internet-access": true,
7 | "dhcp": true
8 | },
9 | "quotas": {
10 | "cores": 30,
11 | "instances": 75,
12 | "ram": 184320
13 | },
14 | "quotasUsed": {
15 | "cores": 2,
16 | "instances": 7,
17 | "ram": 2048,
18 | "gpu": 0
19 | }
20 | },
21 | {
22 | "id": "e2fdb33c-37ae-4b22-878d-49e4758a51f0",
23 | "name": "OtherProject",
24 | "settings": {
25 | "internet-access": true,
26 | "dhcp": true
27 | },
28 | "quotas": {
29 | "cores": 30,
30 | "instances": 75,
31 | "ram": 184320
32 | },
33 | "quotasUsed": {
34 | "cores": 2,
35 | "instances": 7,
36 | "ram": 2048,
37 | "gpu": 0
38 | }
39 | }
40 | ]
41 |
--------------------------------------------------------------------------------
/docs/multiversion.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euox pipefail
3 |
4 | declare -a BRANCHES=("main" "release-0.5" "release-0.6" "release-0.7")
5 |
6 | # https://stackoverflow.com/a/246128
7 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
8 | OUTPUT_DIR="${SCRIPT_DIR}/build"
9 |
10 | rm -rf "${OUTPUT_DIR}"
11 | mkdir -p "${OUTPUT_DIR}"
12 |
13 | for BRANCH in "${BRANCHES[@]}"; do
14 | WORKTREE="${OUTPUT_DIR}/.worktree/tmp-docs-${BRANCH}"
15 |
16 | git worktree add --force "${WORKTREE}" "${BRANCH}"
17 |
18 | uv run --project "${WORKTREE}" --isolated --all-packages --group docs \
19 | make -C "${WORKTREE}/docs" html SPHINXOPTS="-D version=${BRANCH}"
20 |
21 | cp -r "${WORKTREE}/docs/build/html" "${OUTPUT_DIR}/${BRANCH}"
22 |
23 | git worktree remove --force "${WORKTREE}"
24 | done
25 |
26 | pushd "${OUTPUT_DIR}"
27 | uvx --from git+https://github.com/steinwurf/versjon --with jinja2 versjon
28 | popd
29 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/streams/encoding_test.py:
--------------------------------------------------------------------------------
1 | from io import BytesIO
2 |
3 | import pytest
4 | from anyio import EndOfStream, create_memory_object_stream
5 | from anyio.streams.stapled import StapledObjectStream
6 |
7 | from .encoding import compress_stream
8 |
9 | pytestmark = pytest.mark.anyio
10 |
11 |
12 | def create_buffer(size):
13 | tx, rx = create_memory_object_stream[bytes](size)
14 | return StapledObjectStream(tx, rx)
15 |
16 |
17 | @pytest.mark.parametrize("compression", [None, "gzip", "xz", "bz2", "zstd"])
18 | async def test_compress_stream(compression):
19 | stream = compress_stream(create_buffer(128), compression)
20 |
21 | await stream.send(b"hello")
22 | await stream.send_eof()
23 |
24 | result = BytesIO()
25 | while True:
26 | try:
27 | result.write(await stream.receive())
28 | except EndOfStream:
29 | break
30 | assert result.getvalue() == b"hello"
31 |
--------------------------------------------------------------------------------
/.devfile.yaml:
--------------------------------------------------------------------------------
1 | schemaVersion: 2.3.0
2 | metadata:
3 | name: jumpstarter-dev
4 | icon: https://jumpstarter.dev/jumpstarter.svg
5 | tags:
6 | - Python
7 | - UV
8 | - Jumpstarter
9 | language: Python
10 | projects:
11 | - name: jumpstarter
12 | git:
13 | remotes:
14 | origin: https://github.com/jumpstarter-dev/jumpstarter.git
15 | components:
16 | - name: runtime
17 | container:
18 | image: quay.io/jumpstarter-dev/jumpstarter-dev:latest
19 | mountSources: true
20 |
21 | commands:
22 | - id: serve-docs
23 | exec:
24 | component: runtime
25 | commandLine: make docs-serve DOC_LISTEN="--host 0.0.0.0"
26 | - id: sync
27 | exec:
28 | component: runtime
29 | commandLine: make sync
30 | - id: clean
31 | exec:
32 | component: runtime
33 | commandLine: make clean
34 | - id: test
35 | exec:
36 | component: runtime
37 | commandLine: make test
38 |
39 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/common.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel
2 |
3 |
4 | class UStreamerState(BaseModel):
5 | class Result(BaseModel):
6 | class Encoder(BaseModel):
7 | type: str
8 | """type of encoder in use, e.g. CPU/GPU"""
9 | quality: int
10 | """encoding quality"""
11 |
12 | class Source(BaseModel):
13 | class Resolution(BaseModel):
14 | width: int
15 | """resolution width"""
16 | height: int
17 | """resolution height"""
18 |
19 | online: bool
20 | """client active"""
21 | desired_fps: int
22 | """desired fps"""
23 | captured_fps: int
24 | """actual fps"""
25 |
26 | resolution: Resolution
27 |
28 | encoder: Encoder
29 | source: Source
30 |
31 | ok: bool
32 |
33 | result: Result
34 |
--------------------------------------------------------------------------------
/examples/soc-pytest/jumpstarter_example_soc_pytest/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.example.com:443
7 | token: xxxxx
8 | export:
9 | # a DUTLink interface to the DUT
10 | dutlink:
11 | type: jumpstarter_driver_dutlink.driver.Dutlink
12 | config:
13 | storage_device: "/dev/disk/by-id/usb-SanDisk_3.2_Gen_1_5B4C0AB025C0-0:0"
14 | # an HDMI to USB capture card
15 | video:
16 | type: jumpstarter_driver_ustreamer.driver.UStreamer
17 | config:
18 | args:
19 | device: '/dev/v4l/by-path/pci-0000:00:14.0-usbv2-0:3:1.0-video-index0'
20 | resolution: 1920x1080
21 | # a USB camera pointing to the DUT
22 | camera:
23 | type: jumpstarter_driver_ustreamer.driver.UStreamer
24 | config:
25 | args:
26 | device: '/dev/v4l/by-path/pci-0000:00:14.0-usbv2-0:4:1.0-video-index0'
27 | resolution: 1280x720
28 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: demo
6 | endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7 | token: ""
8 | export:
9 | storage:
10 | type: "jumpstarter_driver_flashers.driver.TIJ784S4Flasher"
11 | children:
12 | serial:
13 | ref: "serial"
14 | power:
15 | ref: "power"
16 | # tftp and http driver are automatically created when not specified, cannot be specified via ref
17 | # tftp:
18 | # type: "jumpstarter_driver_tftp.driver.TftpServer"
19 | # http
20 | serial:
21 | type: "jumpstarter_driver_pyserial.driver.PySerial"
22 | config:
23 | url: "/dev/serial/by-id/usb-FTDI_USB__-__Serial_Converter_112214101760A-if00-port0"
24 | baudrate: 115200
25 | power:
26 | type: jumpstarter_driver_yepkit.driver.Ykush
27 | config:
28 | serial: "YK112233"
29 | port: "1"
--------------------------------------------------------------------------------
/packages/jumpstarter-testing/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-testing"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [{ name = "Kirk Brauer", email = "kbrauer@hatci.com" }]
6 | readme = "README.md"
7 | license = "Apache-2.0"
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "jumpstarter",
11 | "pytest>=8.3.2",
12 | "pytest-anyio>=0.0.0",
13 | "pytest-asyncio>=0.0.0",
14 | "pytest-cov>=5.0.0",
15 | ]
16 |
17 | [dependency-groups]
18 | dev = ["jumpstarter-driver-power"]
19 |
20 | [tool.hatch.metadata.hooks.vcs.urls]
21 | Homepage = "https://jumpstarter.dev"
22 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
23 |
24 | [tool.hatch.version]
25 | source = "vcs"
26 | raw-options = { 'root' = '../../' }
27 |
28 | [build-system]
29 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
30 | build-backend = "hatchling.build"
31 |
32 | [tool.hatch.build.hooks.pin_jumpstarter]
33 | name = "pin_jumpstarter"
34 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-uboot/README.md:
--------------------------------------------------------------------------------
1 | # U-Boot driver
2 |
3 | `jumpstarter-driver-uboot` provides functionality for interacting with the
4 | U-Boot bootloader. This driver does not interact with the DUT directly, instead
5 | it should be configured with backing power and serial drivers.
6 |
7 | ## Installation
8 |
9 | ```{code-block} console
10 | :substitutions:
11 | $ pip3 install --extra-index-url {{index_url}} jumpstarter-driver-uboot
12 | ```
13 |
14 | ## Configuration
15 |
16 | Example configuration:
17 |
18 | ```{literalinclude} uboot.yaml
19 | :language: yaml
20 | ```
21 |
22 | ```{doctest}
23 | :hide:
24 | >>> from jumpstarter.config.exporter import ExporterConfigV1Alpha1DriverInstance
25 | >>> ExporterConfigV1Alpha1DriverInstance.from_path("source/reference/package-apis/drivers/uboot.yaml").instantiate()
26 | UbootConsole(...)
27 | ```
28 |
29 | ## API Reference
30 |
31 | ```{eval-rst}
32 | .. autoclass:: jumpstarter_driver_uboot.client.UbootConsoleClient()
33 | :members:
34 | ```
35 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-qemu/jumpstarter_driver_qemu/client.py:
--------------------------------------------------------------------------------
1 | from contextlib import contextmanager
2 |
3 | from jumpstarter_driver_composite.client import CompositeClient
4 | from jumpstarter_driver_network.adapters import FabricAdapter, NovncAdapter
5 |
6 |
7 | class QemuClient(CompositeClient):
8 | @property
9 | def hostname(self) -> str:
10 | return self.call("get_hostname")
11 |
12 | @property
13 | def username(self) -> str:
14 | return self.call("get_username")
15 |
16 | @property
17 | def password(self) -> str:
18 | return self.call("get_password")
19 |
20 | @contextmanager
21 | def novnc(self):
22 | with NovncAdapter(client=self.vnc) as url:
23 | yield url
24 |
25 | @contextmanager
26 | def shell(self):
27 | with FabricAdapter(
28 | client=self.ssh,
29 | user=self.username,
30 | connect_kwargs={"password": self.password},
31 | ) as conn:
32 | yield conn
33 |
--------------------------------------------------------------------------------
/.github/workflows/trigger-packages-index.yaml:
--------------------------------------------------------------------------------
1 | name: Trigger Packages Index Generation
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - release-*
8 | tags:
9 | - "*"
10 |
11 | jobs:
12 | trigger-packages-index:
13 | runs-on: ubuntu-latest
14 | if: ${{ github.repository_owner == 'jumpstarter-dev' }}
15 | steps:
16 | - uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
17 | id: app-token
18 | with:
19 | app-id: ${{ secrets.JUMPSTARTER_BACKPORT_BOT_APP_ID }}
20 | private-key: ${{ secrets.JUMPSTARTER_BACKPORT_BOT_PRIVATE_KEY }}
21 | owner: ${{ github.repository_owner }}
22 | repositories: |
23 | packages
24 |
25 | - name: Trigger packages repository index generation
26 | uses: peter-evans/repository-dispatch@v3
27 | with:
28 | token: ${{ steps.app-token.outputs.token }}
29 | repository: jumpstarter-dev/packages
30 | event-type: generate-index
31 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli/jumpstarter_cli/jmp.py:
--------------------------------------------------------------------------------
1 | import click
2 | from jumpstarter_cli_admin import admin
3 | from jumpstarter_cli_common.alias import AliasedGroup
4 | from jumpstarter_cli_common.opt import opt_log_level
5 | from jumpstarter_cli_common.version import version
6 | from jumpstarter_cli_driver import driver
7 |
8 | from .config import config
9 | from .create import create
10 | from .delete import delete
11 | from .get import get
12 | from .login import login
13 | from .run import run
14 | from .shell import shell
15 | from .update import update
16 |
17 |
18 | @click.group(cls=AliasedGroup)
19 | @opt_log_level
20 | def jmp():
21 | """The Jumpstarter CLI"""
22 |
23 |
24 | jmp.add_command(create)
25 | jmp.add_command(delete)
26 | jmp.add_command(update)
27 | jmp.add_command(get)
28 | jmp.add_command(shell)
29 | jmp.add_command(run)
30 | jmp.add_command(login)
31 | jmp.add_command(config)
32 |
33 | jmp.add_command(driver)
34 | jmp.add_command(admin)
35 | jmp.add_command(version)
36 |
37 | if __name__ == "__main__":
38 | jmp()
39 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/driver/decorators_test.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from . import export
4 | from .decorators import (
5 | MARKER_DRIVERCALL,
6 | MARKER_MAGIC,
7 | MARKER_STREAMING_DRIVERCALL,
8 | )
9 |
10 |
11 | class Functions:
12 | @export
13 | def function(self):
14 | pass
15 |
16 | @export
17 | async def asyncfunction(self):
18 | pass
19 |
20 | @export
21 | def generator(self):
22 | yield
23 |
24 | @export
25 | async def asyncgenerator(self):
26 | yield
27 |
28 |
29 | def test_driver_decorators():
30 | functions = Functions()
31 |
32 | assert getattr(functions.function, MARKER_DRIVERCALL) == MARKER_MAGIC
33 | assert getattr(functions.asyncfunction, MARKER_DRIVERCALL) == MARKER_MAGIC
34 | assert getattr(functions.generator, MARKER_STREAMING_DRIVERCALL) == MARKER_MAGIC
35 | assert getattr(functions.asyncgenerator, MARKER_STREAMING_DRIVERCALL) == MARKER_MAGIC
36 |
37 | with pytest.raises(ValueError):
38 | export(None)
39 |
--------------------------------------------------------------------------------
/packages/jumpstarter-imagehash/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-imagehash"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
7 | { name = "Nick Cao", email = "ncao@redhat.com" },
8 | { name = "Kirk Brauer", email = "kbrauer@hatci.com" },
9 | ]
10 | readme = "README.md"
11 | license = "Apache-2.0"
12 | requires-python = ">=3.11"
13 | dependencies = ["imagehash>=4.3.1", "jumpstarter"]
14 |
15 | [dependency-groups]
16 | dev = ["pytest>=8.3.2", "pytest-cov>=5.0.0"]
17 |
18 | [tool.hatch.metadata.hooks.vcs.urls]
19 | Homepage = "https://jumpstarter.dev"
20 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
21 |
22 | [tool.hatch.version]
23 | source = "vcs"
24 | raw-options = { 'root' = '../../' }
25 |
26 | [build-system]
27 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
28 | build-backend = "hatchling.build"
29 |
30 | [tool.hatch.build.hooks.pin_jumpstarter]
31 | name = "pin_jumpstarter"
32 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/test/data/kernel:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ustreamer/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-ustreamer"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Nick Cao", email = "ncao@redhat.com" },
7 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
8 | { name = "Kirk Brauer", email = "kbrauer@hatci.com" },
9 | ]
10 | readme = "README.md"
11 | license = "Apache-2.0"
12 | requires-python = ">=3.11"
13 | dependencies = ["jumpstarter", "pillow>=10.4.0"]
14 |
15 | [dependency-groups]
16 | dev = ["pytest>=8.3.2", "pytest-cov>=5.0.0"]
17 |
18 | [tool.hatch.metadata.hooks.vcs.urls]
19 | Homepage = "https://jumpstarter.dev"
20 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
21 |
22 | [tool.hatch.version]
23 | source = "vcs"
24 | raw-options = { 'root' = '../../' }
25 |
26 | [build-system]
27 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
28 | build-backend = "hatchling.build"
29 |
30 | [tool.hatch.build.hooks.pin_jumpstarter]
31 | name = "pin_jumpstarter"
32 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/driver/decorators.py:
--------------------------------------------------------------------------------
1 | from inspect import isasyncgenfunction, iscoroutinefunction, isfunction, isgeneratorfunction
2 | from typing import Final
3 |
4 | MARKER_MAGIC: Final[str] = "07c9b9cc"
5 | MARKER_DRIVERCALL: Final[str] = "marker_drivercall"
6 | MARKER_STREAMCALL: Final[str] = "marker_streamcall"
7 | MARKER_STREAMING_DRIVERCALL: Final[str] = "marker_streamingdrivercall"
8 |
9 |
10 | def export(func):
11 | """
12 | Decorator for exporting method as driver call
13 | """
14 | if isasyncgenfunction(func) or isgeneratorfunction(func):
15 | setattr(func, MARKER_STREAMING_DRIVERCALL, MARKER_MAGIC)
16 | elif iscoroutinefunction(func) or isfunction(func):
17 | setattr(func, MARKER_DRIVERCALL, MARKER_MAGIC)
18 | else:
19 | raise ValueError(f"unsupported exported function {func}")
20 | return func
21 |
22 |
23 | def exportstream(func):
24 | """
25 | Decorator for exporting method as stream
26 | """
27 | setattr(func, MARKER_STREAMCALL, MARKER_MAGIC)
28 | return func
29 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/driver.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 |
3 | from jumpstarter.common.exceptions import ConfigurationError
4 | from jumpstarter.driver import Driver, export
5 |
6 |
7 | @dataclass(kw_only=True)
8 | class TMT(Driver):
9 | """ driver for Jumpstarter"""
10 |
11 | reboot_cmd: str = ""
12 | default_username: str = ""
13 | default_password: str = ""
14 |
15 | def __post_init__(self):
16 | if hasattr(super(), "__post_init__"):
17 | super().__post_init__()
18 |
19 | if "ssh" not in self.children:
20 | raise ConfigurationError("'ssh' child is required via ref, or directly as a TcpNetwork driver instance")
21 |
22 |
23 | @classmethod
24 | def client(cls) -> str:
25 | return "jumpstarter_driver_tmt.client.TMTClient"
26 |
27 | @export
28 | def get_reboot_cmd(self):
29 | return self.reboot_cmd
30 |
31 | @export
32 | def get_default_user_pass(self):
33 | return self.default_username, self.default_password
34 |
35 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "tamasfe.even-better-toml",
4 | "tekumara.typos-vscode",
5 | "charliermarsh.ruff",
6 | "codezombiech.gitignore",
7 | "littlefoxteam.vscode-python-test-adapter",
8 | "hbenl.vscode-test-explorer",
9 | "ryanluker.vscode-coverage-gutters",
10 | "lextudio.restructuredtext",
11 | "trond-snekvik.simple-rst",
12 | "swyddfa.esbonio",
13 | "ExecutableBookProject.myst-highlight",
14 | "eamodio.gitlens",
15 | "kevinrose.vsc-python-indent",
16 | "mosapride.zenkaku",
17 | "ms-azuretools.vscode-docker",
18 | "ms-python.python",
19 | "njpwerner.autodocstring",
20 | "pkief.material-icon-theme",
21 | "shardulm94.trailing-spaces",
22 | "usernamehw.errorlens",
23 | "yzhang.markdown-all-in-one",
24 | "ms-vscode.makefile-tools",
25 | "cnshenj.vscode-task-manager"
26 | ],
27 | "unwantedRecommendations": [
28 | "ms-python.autopep8"
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-renesas.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: FlashBundleManifest
3 | metadata:
4 | name: rcar-s4
5 | spec:
6 | manufacturer: Renesas
7 | link: "https://www.renesas.com/en/products/automotive-products/automotive-system-chips-socs/r-car-s4-automotive-system-chip-soc-car-servercommunication-gateway"
8 | # boot default configuration R-Car S4 Spider, for S4SK use "bootm 0x58000000#s4sk"
9 | bootcmd: "bootm 0x58000000"
10 | shelltype: "busybox"
11 | login:
12 | login_prompt: "login:"
13 | username: "root"
14 | prompt: "#"
15 | default_target: "emmc"
16 | targets:
17 | emmc: "/dev/mmcblk0"
18 | kernel:
19 | file: data/flasher-automotive.itb
20 | address: "0x58000000"
21 | dtb:
22 | default: spider
23 | address: "0x48000000"
24 | variants:
25 | spider:
26 | bootcmd: "bootm 0x58000000#spider"
27 | s4sk:
28 | bootcmd: "bootm 0x58000000#s4sk"
29 | custom:
30 | bootcmd: "bootm 0x58000000:kernel 0x58000000:initrd 0x48000000"
31 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ustreamer/README.md:
--------------------------------------------------------------------------------
1 | # Ustreamer driver
2 |
3 | `jumpstarter-driver-ustreamer` provides functionality for using the ustreamer
4 | video streaming server driven by the jumpstarter exporter. This driver takes a
5 | video device and exposes both snapshot and streaming interfaces.
6 |
7 | ## Installation
8 |
9 | ```{code-block} console
10 | :substitutions:
11 | $ pip3 install --extra-index-url {{index_url}} jumpstarter-driver-ustreamer
12 | ```
13 |
14 | ## Configuration
15 |
16 | Example configuration:
17 |
18 | ```{literalinclude} ustreamer.yaml
19 | :language: yaml
20 | ```
21 |
22 | ```{doctest}
23 | :hide:
24 | >>> from jumpstarter.config.exporter import ExporterConfigV1Alpha1DriverInstance
25 | >>> ExporterConfigV1Alpha1DriverInstance.from_path("source/reference/package-apis/drivers/ustreamer.yaml").instantiate()
26 | Traceback (most recent call last):
27 | ...
28 | io.UnsupportedOperation: fileno
29 | ```
30 |
31 | ## API Reference
32 |
33 | ```{eval-rst}
34 | .. autoclass:: jumpstarter_driver_ustreamer.client.UStreamerClient()
35 | :members:
36 | ```
37 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-sdwire/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-sdwire"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [{ name = "Nick Cao", email = "ncao@redhat.com" }]
6 | readme = "README.md"
7 | license = "Apache-2.0"
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "jumpstarter",
11 | "jumpstarter-driver-opendal",
12 | "pyusb>=1.2.1",
13 | "pyudev>=0.24.3",
14 | ]
15 |
16 | [project.entry-points."jumpstarter.drivers"]
17 | SDWire = "jumpstarter_driver_sdwire.driver:SDWire"
18 |
19 | [dependency-groups]
20 | dev = ["pytest>=8.3.2", "pytest-cov>=5.0.0"]
21 |
22 | [tool.hatch.metadata.hooks.vcs.urls]
23 | Homepage = "https://jumpstarter.dev"
24 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
25 |
26 | [tool.hatch.version]
27 | source = "vcs"
28 | raw-options = { 'root' = '../../' }
29 |
30 | [build-system]
31 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
32 | build-backend = "hatchling.build"
33 |
34 | [tool.hatch.build.hooks.pin_jumpstarter]
35 | name = "pin_jumpstarter"
36 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tasmota/jumpstarter_driver_tasmota/driver_test.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest_mqtt.model import MqttMessage
3 |
4 | from .driver import TasmotaPower
5 | from jumpstarter.common.utils import serve
6 |
7 |
8 | @pytest.mark.skip("requires docker")
9 | def test_tasmota_power(mosquitto, capmqtt):
10 | cmnd_topic = "cmnd/tasmota_6990F2/POWER"
11 | stat_topic = "stat/tasmota_6990F2/POWER"
12 |
13 | with serve(
14 | TasmotaPower(
15 | host=mosquitto[0],
16 | port=int(mosquitto[1]),
17 | tls=False,
18 | transport="tcp",
19 | cmnd_topic=cmnd_topic,
20 | stat_topic=stat_topic,
21 | )
22 | ) as client:
23 | capmqtt.publish(topic=stat_topic, payload="ON")
24 | client.on()
25 | assert MqttMessage(topic=cmnd_topic, payload=b"ON", userdata=None) in capmqtt.messages
26 |
27 | capmqtt.publish(topic=stat_topic, payload="OFF")
28 | client.off()
29 | assert MqttMessage(topic=cmnd_topic, payload=b"OFF", userdata=None) in capmqtt.messages
30 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/dbus.py:
--------------------------------------------------------------------------------
1 | from contextlib import contextmanager
2 | from os import environ, getenv
3 | from typing import TYPE_CHECKING
4 |
5 | from .portforward import TcpPortforwardAdapter
6 |
7 | if TYPE_CHECKING:
8 | from ..client import DbusNetworkClient
9 |
10 |
11 | @contextmanager
12 | def DbusAdapter(*, client: "DbusNetworkClient"):
13 | match client.kind:
14 | case "system":
15 | varname = "DBUS_SYSTEM_BUS_ADDRESS"
16 | pass
17 | case "session":
18 | varname = "DBUS_SESSION_BUS_ADDRESS"
19 | pass
20 | case _:
21 | raise ValueError(f"invalid bus type: {client.kind}")
22 |
23 | oldenv = getenv(varname)
24 |
25 | with TcpPortforwardAdapter(client=client) as addr:
26 | environ[varname] = f"tcp:host={addr[0]},port={addr[1]}"
27 |
28 | try:
29 | yield
30 | finally:
31 | if oldenv is None:
32 | del environ[varname]
33 | else:
34 | environ[varname] = oldenv
35 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-sdwire/README.md:
--------------------------------------------------------------------------------
1 | # SDWire driver
2 |
3 | `jumpstarter-driver-sdwire` provides functionality for using the SDWire storage
4 | multiplexer. This device multiplexes an SD card between the DUT and the exporter
5 | host.
6 |
7 | ## Installation
8 |
9 | ```{code-block} console
10 | :substitutions:
11 | $ pip3 install --extra-index-url {{index_url}} jumpstarter-driver-sdwire
12 | ```
13 |
14 | ## Configuration
15 |
16 | Example configuration:
17 |
18 | ```{literalinclude} sdwire.yaml
19 | :language: yaml
20 | ```
21 |
22 | ```{doctest}
23 | :hide:
24 | >>> from jumpstarter.config.exporter import ExporterConfigV1Alpha1DriverInstance
25 | >>> ExporterConfigV1Alpha1DriverInstance.from_path("source/api-reference/drivers/sdwire.yaml").instantiate()
26 | Traceback (most recent call last):
27 | ...
28 | FileNotFoundError: failed to find sd-wire device
29 | ```
30 |
31 | ## API Reference
32 |
33 | The SDWire driver implements the `StorageMuxClient` class, which is a generic
34 | storage class.
35 |
36 | ```{eval-rst}
37 | .. autoclass:: jumpstarter_driver_opendal.client.StorageMuxClient()
38 | :members:
39 | ```
40 |
--------------------------------------------------------------------------------
/packages/jumpstarter-protocol/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-protocol"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [{ name = "Kirk Brauer", email = "kbrauer@hatci.com" }]
6 | readme = "README.md"
7 | license = "Apache-2.0"
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "googleapis-common-protos>=1.69.1",
11 | "grpcio>=1.66.1",
12 | "protobuf>=6.30.1",
13 | ]
14 |
15 | [dependency-groups]
16 | dev = [
17 | "pytest>=8.3.2",
18 | "pytest-anyio>=0.0.0",
19 | "pytest-asyncio>=0.0.0",
20 | "pytest-cov>=5.0.0",
21 | ]
22 |
23 | [tool.hatch.build.targets.wheel]
24 | packages = ["jumpstarter_protocol"]
25 |
26 | [tool.hatch.metadata.hooks.vcs.urls]
27 | Homepage = "https://jumpstarter.dev"
28 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
29 |
30 | [tool.hatch.version]
31 | source = "vcs"
32 | raw-options = { 'root' = '../../' }
33 |
34 | [build-system]
35 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
36 | build-backend = "hatchling.build"
37 |
38 | [tool.hatch.build.hooks.pin_jumpstarter]
39 | name = "pin_jumpstarter"
40 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-opendal/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-opendal"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
7 | { name = "Nick Cao", email = "ncao@redhat.com" },
8 | ]
9 | readme = "README.md"
10 | license = "Apache-2.0"
11 | requires-python = ">=3.11"
12 | dependencies = ["jumpstarter", "opendal>=0.45.8", "click>=8.1.7.2"]
13 |
14 | [project.entry-points."jumpstarter.adapters"]
15 | Opendal = "jumpstarter_driver_opendal.adapters:OpendalAdapter"
16 |
17 | [dependency-groups]
18 | dev = ["pytest>=8.3.2", "pytest-cov>=5.0.0"]
19 |
20 | [tool.hatch.metadata.hooks.vcs.urls]
21 | Homepage = "https://jumpstarter.dev"
22 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
23 |
24 | [tool.hatch.version]
25 | source = "vcs"
26 | raw-options = { 'root' = '../../' }
27 |
28 | [build-system]
29 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
30 | build-backend = "hatchling.build"
31 |
32 | [tool.hatch.build.hooks.pin_jumpstarter]
33 | name = "pin_jumpstarter"
34 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-power/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-power"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
7 | { name = "Nick Cao", email = "ncao@redhat.com" },
8 | ]
9 | readme = "README.md"
10 | license = "Apache-2.0"
11 | requires-python = ">=3.11"
12 | dependencies = ["jumpstarter", "pyserial>=3.5", "click>=8.1.7.2"]
13 |
14 | [project.entry-points."jumpstarter.drivers"]
15 | MockPower = "jumpstarter_driver_power.driver:MockPower"
16 |
17 | [dependency-groups]
18 | dev = ["pytest>=8.3.2", "pytest-cov>=5.0.0", "trio>=0.28.0"]
19 |
20 | [tool.hatch.metadata.hooks.vcs.urls]
21 | Homepage = "https://jumpstarter.dev"
22 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
23 |
24 | [tool.hatch.version]
25 | source = "vcs"
26 | raw-options = { 'root' = '../../' }
27 |
28 | [build-system]
29 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
30 | build-backend = "hatchling.build"
31 |
32 | [tool.hatch.build.hooks.pin_jumpstarter]
33 | name = "pin_jumpstarter"
34 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ridesx/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: jumpstarter-lab
5 | name: qc
6 | endpoint:
7 | tls:
8 | ca: ""
9 | insecure: true
10 | token:
11 | export:
12 | storage:
13 | type: "jumpstarter_driver_ridesx.driver.RideSXDriver"
14 | config:
15 | log_level: "DEBUG"
16 | children:
17 | serial:
18 | type: "jumpstarter_driver_pyserial.driver.PySerial"
19 | config:
20 | log_level: "DEBUG"
21 | url: "/dev/ttyACM0"
22 | baudrate: 115200
23 | power:
24 | type: "jumpstarter_driver_ridesx.driver.RideSXPowerDriver"
25 | config:
26 | log_level: "DEBUG"
27 | children:
28 | serial:
29 | type: "jumpstarter_driver_pyserial.driver.PySerial"
30 | config:
31 | log_level: "DEBUG"
32 | url: "/dev/ttyACM0"
33 | baudrate: 115200
34 | serial:
35 | type: "jumpstarter_driver_pyserial.driver.PySerial"
36 | config:
37 | log_level: "DEBUG"
38 | url: "/dev/ttyUSB1"
39 | baudrate: 115200
40 |
--------------------------------------------------------------------------------
/.github/workflows/build_oci_bundle.yaml:
--------------------------------------------------------------------------------
1 | name: Build and push buildroot-based flasher OCI bundle
2 | on:
3 | workflow_dispatch:
4 |
5 | jobs:
6 | build-fits:
7 | runs-on: ubuntu-24.04-arm
8 | container: fedora:42
9 | steps:
10 | - name: Checkout repository
11 | uses: actions/checkout@v4
12 | with:
13 | fetch-depth: 0
14 |
15 | - name: Run build_fits.sh
16 | run: |
17 | cd packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb
18 | ./build_fits.sh
19 |
20 | - name: Upload FIT artifacts
21 | uses: actions/upload-artifact@v4
22 | with:
23 | name: FIT-images
24 | path: packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/data/*.itb
25 |
26 | - name: Run build_bundle.sh for aarch64-itb
27 | run: |
28 | cd packages/jumpstarter-driver-flashers/oci_bundles && dnf install -y oras
29 | oras login quay.io -u jumpstarter-dev+jumpstarter_ci --password-stdin <<< "${{ secrets.QUAY_TOKEN }}"
30 | ./build_bundle.sh quay.io/jumpstarter-dev/jumpstarter-flasher-aarch64-itb:latest aarch64-itb
31 |
--------------------------------------------------------------------------------
/packages/jumpstarter-kubernetes/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-kubernetes"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [{ name = "Kirk Brauer", email = "kbrauer@hatci.com" }]
6 | readme = "README.md"
7 | license = "Apache-2.0"
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "jumpstarter",
11 | "pydantic>=2.8.2",
12 | "kubernetes>=31.0.0",
13 | "kubernetes-asyncio>=31.1.0",
14 | "aiohttp>=3.11.18",
15 | "semver~=2.13",
16 | "packaging>=25.0",
17 | ]
18 |
19 | [dependency-groups]
20 | dev = [
21 | "pytest>=8.3.2",
22 | "pytest-anyio>=0.0.0",
23 | "pytest-asyncio>=0.0.0",
24 | "pytest-cov>=5.0.0",
25 | ]
26 |
27 | [tool.hatch.metadata.hooks.vcs.urls]
28 | Homepage = "https://jumpstarter.dev"
29 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
30 |
31 | [tool.hatch.version]
32 | source = "vcs"
33 | raw-options = { 'root' = '../../' }
34 |
35 | [build-system]
36 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
37 | build-backend = "hatchling.build"
38 |
39 | [tool.hatch.build.hooks.pin_jumpstarter]
40 | name = "pin_jumpstarter"
41 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-energenie/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-energenie"
3 | dynamic = ["version", "urls"]
4 | description = "Energenie is an advanced surge protector with power management features"
5 | readme = "README.md"
6 | license = { text = "Apache-2.0" }
7 | authors = [
8 | { name = "Enric Balletbo i Serra", email = "eballetbo@redhat.com" }
9 | ]
10 | requires-python = ">=3.11"
11 | dependencies = [
12 | "anyio>=4.10.0",
13 | "jumpstarter",
14 | "jumpstarter-driver-power"
15 | ]
16 |
17 | [project.entry-points."jumpstarter.drivers"]
18 | EnerGenie = "jumpstarter_driver_energenie.driver:EnerGenie"
19 |
20 | [dependency-groups]
21 | dev = [
22 | "pytest-cov>=6.0.0",
23 | "pytest>=8.3.3",
24 | "pytest-httpserver>=1.0.0",
25 | ]
26 |
27 | [tool.hatch.metadata.hooks.vcs.urls]
28 | Homepage = "https://jumpstarter.dev"
29 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
30 |
31 | [tool.hatch.version]
32 | source = "vcs"
33 | raw-options = { 'root' = '../../'}
34 |
35 | [build-system]
36 | requires = ["hatchling", "hatch-vcs"]
37 | build-backend = "hatchling.build"
38 |
--------------------------------------------------------------------------------
/examples/soc-pytest/jumpstarter_example_soc_pytest/image/scripts/download-latest-raspbian:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 | #LATEST_URL=$(wget -O /dev/null -o - --max-redirect=0 https://downloads.raspberrypi.org/raspios_lite_armhf_latest 2>/dev/null| sed -n "s/^Location: \(.*\) \[following\]$/\1/p")
4 | LATEST_URL=$(curl https://downloads.raspberrypi.org/raspios_lite_armhf_latest -v 2>&1 | sed -n "s/< location: \(.*\)\r$/\1/p")
5 | echo $LATEST_URL
6 | CACHE="./images"
7 | wget "${LATEST_URL}" -np -m -A '*img.xz' -c -P "${CACHE}"
8 | # use the latest compose image
9 | LATEST_IMG=$(ls -Art "${CACHE}/downloads.raspberrypi.org/raspios_lite_armhf/images"/*/*.img.xz | tail -n 1)
10 |
11 | echo "Latest image: ${LATEST_IMG}"
12 |
13 | # calculate full path to LATEST_IMG
14 | LATEST_IMG_FULLPATH=$(readlink -f ${LATEST_IMG})
15 | EXISTING_LINK=$(readlink "${CACHE}/latest.raw.xz" || true )
16 | # if the link has changed, update the link
17 | if [[ "${LATEST_IMG_FULLPATH}" != "${EXISTING_LINK}" ]]; then
18 | echo "Updating link from latest.raw.xz -> ${LATEST_IMG}"
19 | ln -fs "${LATEST_IMG_FULLPATH}" "${CACHE}/latest.raw.xz"
20 | else
21 | echo "We are up-to-date."
22 | fi
23 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ble/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-ble"
3 | dynamic = ["version", "urls"]
4 | description = "Bluetooth Low Energy (BLE) driver"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [{ name = "Andreas Karner", email = "andreas.karner@outlook.com" }]
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "anyio>=4.10.0",
11 | "jumpstarter",
12 | "bleak>=1.1.1",
13 | ]
14 |
15 | [tool.hatch.version]
16 | source = "vcs"
17 | raw-options = { 'root' = '../../' }
18 |
19 | [tool.hatch.metadata.hooks.vcs.urls]
20 | Homepage = "https://jumpstarter.dev"
21 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
22 |
23 | [tool.pytest.ini_options]
24 | addopts = "--cov --cov-report=html --cov-report=xml"
25 | log_cli = true
26 | log_cli_level = "INFO"
27 | testpaths = ["jumpstarter_driver_ble"]
28 |
29 | [build-system]
30 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
31 | build-backend = "hatchling.build"
32 |
33 | [dependency-groups]
34 | dev = ["pytest-cov>=6.0.0", "pytest>=8.3.3"]
35 |
36 | [tool.hatch.build.hooks.pin_jumpstarter]
37 | name = "pin_jumpstarter"
38 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-gpiod/jumpstarter_driver_gpiod/conftest.py:
--------------------------------------------------------------------------------
1 | import platform
2 |
3 | import pytest
4 |
5 | # Skip all tests on Darwin (macOS) due to missing gpiod module
6 | pytestmark = pytest.mark.skipif(platform.system() == "Darwin", reason="gpiod module not available on Darwin/macOS")
7 |
8 |
9 | # Add test utilities for GPIO testing
10 | @pytest.fixture
11 | def mock_gpiod_values():
12 | """Provide mock gpiod value constants for testing"""
13 | return {"ACTIVE": 1, "INACTIVE": 0, "RISING_EDGE": "rising", "FALLING_EDGE": "falling"}
14 |
15 |
16 | @pytest.fixture
17 | def mock_gpiod_directions():
18 | """Provide mock gpiod direction constants for testing"""
19 | return {"INPUT": "input", "OUTPUT": "output"}
20 |
21 |
22 | @pytest.fixture
23 | def mock_gpiod_drives():
24 | """Provide mock gpiod drive constants for testing"""
25 | return {"PUSH_PULL": "push_pull", "OPEN_DRAIN": "open_drain", "OPEN_SOURCE": "open_source"}
26 |
27 |
28 | @pytest.fixture
29 | def mock_gpiod_biases():
30 | """Provide mock gpiod bias constants for testing"""
31 | return {"AS_IS": "as_is", "PULL_UP": "pull_up", "PULL_DOWN": "pull_down", "DISABLED": "disabled"}
32 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-iscsi/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-iscsi"
3 | dynamic = ["version", "urls"]
4 | description = "Exporter ISCSI service driver"
5 | readme = "README.md"
6 | authors = [{ name = "Benny Zlotnik", email = "bzlotnik@redhat.com" }]
7 | requires-python = ">=3.11"
8 | dependencies = [
9 | "anyio>=4.10.0",
10 | "jumpstarter",
11 | "jumpstarter-driver-composite",
12 | "jumpstarter-driver-opendal",
13 | "click>=8.1.8",
14 | "rtslib-fb",
15 | "requests>=2.32.5"
16 | ]
17 |
18 | [tool.hatch.version]
19 | source = "vcs"
20 | raw-options = { 'root' = '../../' }
21 |
22 | [tool.hatch.metadata.hooks.vcs.urls]
23 | Homepage = "https://jumpstarter.dev"
24 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
25 |
26 | [tool.pytest.ini_options]
27 | asyncio_mode = "strict"
28 | asyncio_default_fixture_loop_scope = "function"
29 | testpaths = ["src"]
30 |
31 | [build-system]
32 | requires = ["hatchling", "hatch-vcs"]
33 | build-backend = "hatchling.build"
34 |
35 | [dependency-groups]
36 | dev = [
37 | "pytest-cov>=6.0.0",
38 | "pytest>=8.3.3",
39 | "pytest-asyncio>=0.24.0",
40 | ]
41 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-composite/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-composite"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
7 | { name = "Nick Cao", email = "ncao@redhat.com" },
8 | ]
9 | readme = "README.md"
10 | license = "Apache-2.0"
11 | requires-python = ">=3.11"
12 | dependencies = ["jumpstarter", "click>=8.1.7.2"]
13 |
14 | [project.entry-points."jumpstarter.drivers"]
15 | Composite = "jumpstarter_driver_composite.driver:Composite"
16 | Proxy = "jumpstarter_driver_composite.driver:Proxy"
17 |
18 | [dependency-groups]
19 | dev = ["pytest>=8.3.2", "pytest-cov>=5.0.0", "jumpstarter-driver-power"]
20 |
21 | [tool.hatch.metadata.hooks.vcs.urls]
22 | Homepage = "https://jumpstarter.dev"
23 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
24 |
25 | [tool.hatch.version]
26 | source = "vcs"
27 | raw-options = { 'root' = '../../' }
28 |
29 | [build-system]
30 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
31 | build-backend = "hatchling.build"
32 |
33 | [tool.hatch.build.hooks.pin_jumpstarter]
34 | name = "pin_jumpstarter"
35 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-pyserial/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-pyserial"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
7 | { name = "Nick Cao", email = "ncao@redhat.com" },
8 | ]
9 | readme = "README.md"
10 | license = "Apache-2.0"
11 | requires-python = ">=3.11"
12 | dependencies = [
13 | "jumpstarter",
14 | "jumpstarter-driver-network",
15 | "pyserial>=3.5",
16 | "click>=8.1.7.2",
17 | "pyserial-asyncio>=0.6",
18 | ]
19 |
20 | [dependency-groups]
21 | dev = [
22 | "pytest>=8.3.2",
23 | "pytest-cov>=5.0.0",
24 | "types-pexpect>=4.9.0.20241208",
25 | "types-pyserial>=3.5.0.20250130",
26 | ]
27 |
28 | [tool.hatch.metadata.hooks.vcs.urls]
29 | Homepage = "https://jumpstarter.dev"
30 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
31 |
32 | [tool.hatch.version]
33 | source = "vcs"
34 | raw-options = { 'root' = '../../' }
35 |
36 | [build-system]
37 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
38 | build-backend = "hatchling.build"
39 |
40 | [tool.hatch.build.hooks.pin_jumpstarter]
41 | name = "pin_jumpstarter"
42 |
--------------------------------------------------------------------------------
/__templates__/driver/pyproject.toml.tmpl:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-${DRIVER_NAME}"
3 | dynamic = ["version", "urls"]
4 | description = "Add your description here"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [
8 | { name = "${AUTHOR_NAME}", email = "${AUTHOR_EMAIL}" }
9 | ]
10 | requires-python = ">=3.11"
11 | dependencies = [
12 | "anyio>=4.10.0",
13 | "jumpstarter",
14 | ]
15 |
16 | [tool.hatch.version]
17 | source = "vcs"
18 | raw-options = { 'root' = '../../'}
19 |
20 | [tool.hatch.metadata.hooks.vcs.urls]
21 | Homepage = "https://jumpstarter.dev"
22 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
23 |
24 | [tool.pytest.ini_options]
25 | addopts = "--cov --cov-report=html --cov-report=xml"
26 | log_cli = true
27 | log_cli_level = "INFO"
28 | testpaths = ["jumpstarter_driver_${DRIVER_NAME}"]
29 | asyncio_mode = "auto"
30 |
31 | [build-system]
32 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
33 | build-backend = "hatchling.build"
34 |
35 | [tool.hatch.build.hooks.pin_jumpstarter]
36 | name = "pin_jumpstarter"
37 |
38 | [dependency-groups]
39 | dev = [
40 | "pytest-cov>=6.0.0",
41 | "pytest>=8.3.3",
42 | ]
43 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-admin/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-cli-admin"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [{ name = "Kirk Brauer", email = "kbrauer@hatci.com" }]
6 | readme = "README.md"
7 | license = "Apache-2.0"
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "grpcio-reflection>=1.60.0",
11 | "jumpstarter-cli-common",
12 | "jumpstarter-kubernetes",
13 | ]
14 |
15 | [dependency-groups]
16 | dev = [
17 | "pytest>=8.3.2",
18 | "pytest-anyio>=0.0.0",
19 | "pytest-asyncio>=0.0.0",
20 | "pytest-cov>=5.0.0",
21 | ]
22 |
23 | [project.scripts]
24 | jmp-admin = "jumpstarter_cli_admin:admin"
25 |
26 | [tool.hatch.build.targets.wheel]
27 | packages = ["jumpstarter_cli_admin"]
28 |
29 | [tool.hatch.metadata.hooks.vcs.urls]
30 | Homepage = "https://jumpstarter.dev"
31 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
32 |
33 | [tool.hatch.version]
34 | source = "vcs"
35 | raw-options = { 'root' = '../../' }
36 |
37 | [build-system]
38 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
39 | build-backend = "hatchling.build"
40 |
41 | [tool.hatch.build.hooks.pin_jumpstarter]
42 | name = "pin_jumpstarter"
43 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-probe-rs/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-probe-rs"
3 | dynamic = ["version", "urls"]
4 | description = "rust probe-rs driver for jumpstarter"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [{ name = "Miguel Angel Ajo", email = "miguelangel@ajo.es" }]
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "anyio>=4.10.0",
11 | "click>=8.1.7.2",
12 | "jumpstarter",
13 | "jumpstarter-driver-opendal",
14 | ]
15 |
16 | [tool.hatch.version]
17 | source = "vcs"
18 | raw-options = { 'root' = '../../' }
19 |
20 | [tool.hatch.metadata.hooks.vcs.urls]
21 | Homepage = "https://jumpstarter.dev"
22 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
23 |
24 | [tool.pytest.ini_options]
25 | addopts = "--cov --cov-report=html --cov-report=xml"
26 | log_cli = true
27 | log_cli_level = "INFO"
28 | testpaths = ["jumpstarter_driver_probe_rs"]
29 |
30 | [build-system]
31 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
32 | build-backend = "hatchling.build"
33 |
34 | [dependency-groups]
35 | dev = ["pytest-cov>=6.0.0", "pytest>=8.3.3"]
36 |
37 | [tool.hatch.build.hooks.pin_jumpstarter]
38 | name = "pin_jumpstarter"
39 |
--------------------------------------------------------------------------------
/conftest.py:
--------------------------------------------------------------------------------
1 | import os
2 | from contextlib import contextmanager
3 |
4 | import pytest
5 |
6 | os.environ["TERM"] = "dumb"
7 |
8 | try:
9 | from jumpstarter.common.utils import serve
10 | from jumpstarter.config.exporter import ExporterConfigV1Alpha1, ExporterConfigV1Alpha1DriverInstance
11 | except ImportError:
12 | # some packages in the workspace does not depend on jumpstarter
13 | pass
14 | else:
15 |
16 | @contextmanager
17 | def run(config):
18 | with serve(ExporterConfigV1Alpha1DriverInstance.from_str(config).instantiate()) as client:
19 | yield client
20 |
21 | @pytest.fixture(autouse=True)
22 | def jumpstarter_namespace(doctest_namespace):
23 | doctest_namespace["serve"] = serve
24 | doctest_namespace["run"] = run
25 |
26 | @pytest.fixture(autouse=True)
27 | def tmp_config_path(tmp_path, monkeypatch):
28 | monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / "client-config"))
29 | monkeypatch.setattr(ExporterConfigV1Alpha1, "BASE_PATH", tmp_path / "exporters")
30 |
31 | @pytest.fixture(autouse=True)
32 | def console_size(monkeypatch):
33 | monkeypatch.setenv("COLUMNS", "1024")
34 | monkeypatch.setenv("LINES", "1024")
35 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-common/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-cli-common"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [{ name = "Kirk Brauer", email = "kbrauer@hatci.com" }]
6 | readme = "README.md"
7 | license = "Apache-2.0"
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "jumpstarter",
11 | "pydantic>=2.8.2",
12 | "click>=8.1.7.2",
13 | "authlib>=1.4.1",
14 | "truststore>=0.10.1",
15 | "joserfc>=1.0.3",
16 | "yarl>=1.18.3",
17 | "rich>=14.0.0",
18 | ]
19 |
20 | [dependency-groups]
21 | dev = [
22 | "pytest>=8.3.2",
23 | "pytest-anyio>=0.0.0",
24 | "pytest-asyncio>=0.0.0",
25 | "pytest-cov>=5.0.0",
26 | ]
27 |
28 | [tool.hatch.build.targets.wheel]
29 | packages = ["jumpstarter_cli_common"]
30 |
31 | [tool.hatch.metadata.hooks.vcs.urls]
32 | Homepage = "https://jumpstarter.dev"
33 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
34 |
35 | [tool.hatch.version]
36 | source = "vcs"
37 | raw-options = { 'root' = '../../' }
38 |
39 | [build-system]
40 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
41 | build-backend = "hatchling.build"
42 |
43 | [tool.hatch.build.hooks.pin_jumpstarter]
44 | name = "pin_jumpstarter"
45 |
--------------------------------------------------------------------------------
/.github/workflows/pr_analytics.yaml:
--------------------------------------------------------------------------------
1 | name: "PR Analytics"
2 | on:
3 | workflow_dispatch:
4 | inputs:
5 | report_date_start:
6 | description: "Report date start(d/MM/yyyy)"
7 | report_date_end:
8 | description: "Report date end(d/MM/yyyy)"
9 | jobs:
10 | create-report:
11 | name: "Create report"
12 | runs-on: ubuntu-latest
13 | permissions:
14 | contents: read
15 | pull-requests: read
16 | issues: write
17 | steps:
18 | - name: "Run script for analytics"
19 | uses: AlexSim93/pull-request-analytics-action@cc57ceb92148c5d5879ca578a2b59f99c3cbe231 # v4.6.1
20 | with:
21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # In the case of a personal access token, it needs to be added to the repository's secrets and used in this field.
22 | GITHUB_REPO_FOR_ISSUE: jumpstarter
23 | GITHUB_OWNER_FOR_ISSUE: jumpstarter-dev
24 | GITHUB_OWNERS_REPOS: jumpstarter-dev/jumpstarter #TODO: check with more repos later, needs PAT: ,jumpstarter-dev/jumpstarter-controller
25 | USE_CHARTS: true
26 | TIMEZONE: "Etc/UTC"
27 | REPORT_DATE_START: ${{ inputs.report_date_start }}
28 | REPORT_DATE_END: ${{ inputs.report_date_end }}
29 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 | HOST ?= 127.0.0.1
11 | PORT ?= 8000
12 |
13 | # Put it first so that "make" without argument is like "make help".
14 | help:
15 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
16 |
17 | # Define custom targets as PHONY to prevent them from being caught by the pattern rule
18 | .PHONY: help Makefile serve multiversion redirect serve-multiversion
19 |
20 | # Catch-all target: route all unknown targets to Sphinx using the new
21 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
22 | %: Makefile
23 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
24 |
25 | serve:
26 | sphinx-autobuild --host $(HOST) --port $(PORT) "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
27 |
28 | multiversion:
29 | ./multiversion.sh
30 |
31 | serve-multiversion:
32 | @echo "Serving multiversion documentation using the HOST variable"
33 | @cd "$(BUILDDIR)" && python -m http.server $(PORT) --bind $(HOST)
34 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tmt/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-tmt"
3 | dynamic = ["version", "urls"]
4 | description = "Add your description here"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [
8 | { name = "Miguel Angel Ajo Pelayo", email = "miguelangel@ajo.es" }
9 | ]
10 | requires-python = ">=3.11"
11 | dependencies = [
12 | "anyio>=4.10.0",
13 | "jumpstarter",
14 | "jumpstarter-driver-network",
15 | "jumpstarter-driver-composite",
16 | ]
17 |
18 | [tool.hatch.version]
19 | source = "vcs"
20 | raw-options = { 'root' = '../../'}
21 |
22 | [tool.hatch.metadata.hooks.vcs.urls]
23 | Homepage = "https://jumpstarter.dev"
24 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
25 |
26 | [tool.pytest.ini_options]
27 | addopts = ""
28 | log_cli = true
29 | log_cli_level = "INFO"
30 | testpaths = ["jumpstarter_driver_tmt"]
31 | asyncio_mode = "auto"
32 |
33 | [build-system]
34 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
35 | build-backend = "hatchling.build"
36 |
37 | [tool.hatch.build.hooks.pin_jumpstarter]
38 | name = "pin_jumpstarter"
39 |
40 | [dependency-groups]
41 | dev = [
42 | "pytest-cov>=6.0.0",
43 | "pytest>=8.3.3",
44 | ]
45 |
--------------------------------------------------------------------------------
/docs/source/introduction/clients.md:
--------------------------------------------------------------------------------
1 | # Clients
2 |
3 | To interact with your target device from a development machine or through a
4 | CI/CD pipeline, you must use a Jumpstarter client. The Python client can be used
5 | either as a library or as a [CLI tool](../reference/man-pages/index.md).
6 |
7 | ## Types of Clients
8 |
9 | Jumpstarter supports two types of client configurations: *local* and *remote*.
10 |
11 | ### Local Clients
12 |
13 | When using Jumpstarter in *local-only* mode, you can use the local client
14 | functionality to directly access your hardware. The local client will
15 | automatically use any drivers that are registered without the need for an
16 | exporter instance running in the background.
17 |
18 | ### Remote Clients
19 |
20 | When using Jumpstarter in *distributed* mode, the client must be configured to
21 | connect to an instance of the Service that can authenticate and route requests
22 | to the appropriate exporter instance.
23 |
24 | The following parameters are required to set up a remote client:
25 |
26 | - The URL of a Service endpoint to connect to
27 | - An authentication token generated by the Service
28 |
29 | ```{note}
30 | The endpoint must be accessible from your client machine to communicate
31 | with the Service.
32 | ```
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/test/manifest.yaml:
--------------------------------------------------------------------------------
1 | # This is a test manifest for the flasher bundle
2 | # It is used to test the flasher bundle, not intended for any production use
3 | apiVersion: jumpstarter.dev/v1alpha1
4 | kind: FlashBundleManifest
5 | metadata:
6 | name: test-bundle
7 | spec:
8 | manufacturer: The Jumpstarter Authors
9 | link: "https://jumpstarter.dev"
10 | bootcmd: "booti 0x82000000 - 0x84000000"
11 | default_target: "usd"
12 | login:
13 | type: "busybox"
14 | login_prompt: "login:"
15 | username: "root"
16 | password: "password"
17 | prompt: "#"
18 | targets:
19 | usd: "/sys/class/block#4fb0000"
20 | emmc: "/sys/class/block#4f80000"
21 | preflash_commands:
22 | - "dd if=/dev/zero of=/dev/mmcblk0 bs=512 count=34"
23 | - "dd if=/dev/zero of=/dev/mmcblk1 bs=512 count=34"
24 | kernel:
25 | file: data/kernel
26 | address: "0x82000000"
27 | initram:
28 | file: data/initramfs
29 | address: "0x83000000"
30 | dtb:
31 | default: test-dtb
32 | address: "0x84000000"
33 | variants:
34 | test-dtb:
35 | file: data/dtbs/test-dtb.dtb
36 | alternate:
37 | file: data/dtbs/alternate.dtb
38 | othercmd:
39 | bootcmd: "bootm"
40 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-corellium/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter_driver_corellium"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [{ name = "Leonardo Rossetti", email = "lrossett@redhat.com" }]
6 | readme = "README.md"
7 | license = "Apache-2.0"
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "jumpstarter",
11 | "jumpstarter-driver-composite",
12 | "jumpstarter-driver-power",
13 | "jumpstarter-driver-network",
14 | "jumpstarter-driver-pyserial",
15 | "click>=8.1.7.2",
16 | ]
17 |
18 | [project.entry-points."jumpstarter.drivers"]
19 | Corellium = "jumpstarter_driver_corellium.driver:Corellium"
20 |
21 | [dependency-groups]
22 | dev = ["pytest>=8.3.2", "pytest-cov>=5.0.0", "trio>=0.28.0", "requests_mock", "pytest-asyncio>=0.25.3"]
23 |
24 | [tool.hatch.metadata.hooks.vcs.urls]
25 | Homepage = "https://jumpstarter.dev"
26 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
27 |
28 | [tool.hatch.version]
29 | source = "vcs"
30 | raw-options = { 'root' = '../../' }
31 |
32 | [build-system]
33 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
34 | build-backend = "hatchling.build"
35 |
36 | [tool.hatch.build.hooks.pin_jumpstarter]
37 | name = "pin_jumpstarter"
38 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tftp/examples/tftp_test.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | import pytest
4 | from jumpstarter_driver_tftp.driver import TftpError
5 | from jumpstarter_testing.pytest import JumpstarterTest
6 |
7 | log = logging.getLogger(__name__)
8 |
9 |
10 | class TestResource(JumpstarterTest):
11 | selector = "board=rpi4"
12 |
13 | @pytest.fixture()
14 | def setup_tftp(self, client):
15 | # Move the setup code to a fixture
16 | client.tftp.start()
17 | yield client
18 | client.tftp.stop()
19 |
20 | def test_tftp_operations(self, setup_tftp):
21 | client = setup_tftp
22 | test_file = "test.bin"
23 |
24 | # Create test file
25 | with open(test_file, "wb") as f:
26 | f.write(b"Hello from TFTP streaming test!")
27 |
28 | try:
29 | # Test upload
30 | client.tftp.put_local_file(test_file)
31 | assert test_file in client.tftp.list_files()
32 |
33 | # Test delete
34 | client.tftp.delete_file(test_file)
35 | assert test_file not in client.tftp.list_files()
36 |
37 | except (TftpError, FileNotFoundError) as e:
38 | pytest.fail(f"Test failed: {e}") # ty: ignore[call-non-callable]
39 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ssh-mitm/examples/exporter.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: ExporterConfig
3 | metadata:
4 | namespace: default
5 | name: ssh-mitm-example
6 | endpoint: "grpc.jumpstarter.example.com:443"
7 | token: "your-exporter-token"
8 | export:
9 | # "j ssh_mitm" command - secure SSH with key on server
10 | ssh_mitm:
11 | type: jumpstarter_driver_ssh.driver.SSHWrapper
12 | config:
13 | # Change to the user you will SSH as on the DUT
14 | default_username: root
15 | children:
16 | tcp:
17 | type: jumpstarter_driver_ssh_mitm.driver.SSHMITM
18 | config:
19 | # Must match the user on the DUT
20 | default_username: root
21 | # Option 1: Path to key file (on exporter machine)
22 | ssh_identity_file: /etc/jumpstarter/ssh_keys/dut_key
23 | # Option 2: Inline key (from secret management)
24 | # ssh_identity: |
25 | # -----BEGIN OPENSSH PRIVATE KEY-----
26 | # ...key content...
27 | # -----END OPENSSH PRIVATE KEY-----
28 | children:
29 | tcp:
30 | type: jumpstarter_driver_network.driver.TcpNetwork
31 | config:
32 | host: 192.168.1.100
33 | port: 22
34 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-can/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-can"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
7 | { name = "Nick Cao", email = "ncao@redhat.com" },
8 | { name = "Kirk Brauer", email = "kbrauer@hatci.com" },
9 | ]
10 | readme = "README.md"
11 | license = "Apache-2.0"
12 | requires-python = ">=3.11"
13 | dependencies = ["jumpstarter", "python-can>=4.5.0", "can-isotp>=2.0.6"]
14 |
15 | [project.entry-points."jumpstarter.drivers"]
16 | Can = "jumpstarter_driver_can.driver:Can"
17 | IsoTpPython = "jumpstarter_driver_can.driver:IsoTpPython"
18 | IsoTpSocket = "jumpstarter_driver_can.driver:IsoTpSocket"
19 |
20 | [dependency-groups]
21 | dev = ["pytest>=8.3.2", "pytest-cov>=5.0.0"]
22 |
23 | [tool.hatch.metadata.hooks.vcs.urls]
24 | Homepage = "https://jumpstarter.dev"
25 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
26 |
27 | [tool.hatch.version]
28 | source = "vcs"
29 | raw-options = { 'root' = '../../' }
30 |
31 | [build-system]
32 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
33 | build-backend = "hatchling.build"
34 |
35 | [tool.hatch.build.hooks.pin_jumpstarter]
36 | name = "pin_jumpstarter"
37 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-http-power/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-http-power"
3 | dynamic = ["version", "urls"]
4 | description = "A power driver for HTTP enabled PDUs or smart sockets, like the Shelly splug"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [
8 | { name = "Miguel Angel Ajo", email = "majopela@redhat.com" }
9 | ]
10 | requires-python = ">=3.11"
11 | dependencies = [
12 | "anyio>=4.10.0",
13 | "jumpstarter",
14 | "jumpstarter-driver-power",
15 | ]
16 |
17 |
18 | [tool.hatch.version]
19 | source = "vcs"
20 | raw-options = { 'root' = '../../' }
21 |
22 | [tool.hatch.metadata.hooks.vcs.urls]
23 | Homepage = "https://jumpstarter.dev"
24 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
25 |
26 | [tool.pytest.ini_options]
27 | addopts = "--cov --cov-report=html --cov-report=xml"
28 | log_cli = true
29 | log_cli_level = "INFO"
30 | testpaths = ["jumpstarter_driver_http_power"]
31 |
32 | [build-system]
33 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
34 | build-backend = "hatchling.build"
35 |
36 | [tool.hatch.build.hooks.pin_jumpstarter]
37 | name = "pin_jumpstarter"
38 |
39 | [dependency-groups]
40 | dev = [
41 | "pytest-cov>=6.0.0",
42 | "pytest>=8.3.3",
43 | ]
44 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-probe-rs/jumpstarter_driver_probe_rs/driver_test.py:
--------------------------------------------------------------------------------
1 | from .driver import ProbeRs
2 | from jumpstarter.common.utils import serve
3 |
4 |
5 | def test_drivers_probe_rs(monkeypatch):
6 | instance = ProbeRs()
7 |
8 | def mock_run_cmd(cmd):
9 | if cmd[0] == "info":
10 | return "Target: nRF52840_xxAA\nFlash size: 1MB"
11 | elif cmd[0] == "read":
12 | return "DEADBEEF CAFEBABE\nCAFE0000 DEAD0000"
13 | return "ok"
14 |
15 | monkeypatch.setattr(instance, "_run_cmd", mock_run_cmd)
16 |
17 | with serve(instance) as client:
18 | info = client.info()
19 | assert "Target:" in info
20 | assert "Flash size:" in info
21 | assert client.reset() == "ok"
22 | assert client.erase() == "ok"
23 | assert client.download_file("/dev/null") == "ok"
24 | assert client.read(32, 0xF000, 4) == [0xDEADBEEF, 0xCAFEBABE, 0xCAFE0000, 0xDEAD0000]
25 |
26 |
27 | def test_drivers_probe_rs_errors(monkeypatch):
28 | instance = ProbeRs()
29 |
30 | monkeypatch.setattr(instance, "_run_cmd", lambda cmd: "") # Simulate error response
31 |
32 | with serve(instance) as client:
33 | assert client.info() == "" # Error case
34 | assert client.reset() == "" # Error case
35 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-http/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-http"
3 | dynamic = ["version", "urls"]
4 | description = "Exporter HTTP service driver"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [{ name = "Benny Zlotnik", email = "bzlotnik@redhat.com" }]
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "anyio>=4.10.0",
11 | "jumpstarter",
12 | "jumpstarter-driver-composite",
13 | "jumpstarter-driver-opendal",
14 | "yarl>=1.18.3",
15 | ]
16 |
17 | [tool.hatch.version]
18 | source = "vcs"
19 | raw-options = { 'root' = '../../' }
20 |
21 | [tool.hatch.metadata.hooks.vcs.urls]
22 | Homepage = "https://jumpstarter.dev"
23 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
24 |
25 | [tool.pytest.ini_options]
26 | asyncio_mode = "strict"
27 | asyncio_default_fixture_loop_scope = "function"
28 | testpaths = ["src"]
29 |
30 | [build-system]
31 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
32 | build-backend = "hatchling.build"
33 |
34 | [dependency-groups]
35 | dev = [
36 | "pytest-cov>=6.0.0",
37 | "pytest>=8.3.3",
38 | "pytest-asyncio>=0.0.0",
39 | "pytest-asyncio>=0.24.0",
40 | ]
41 |
42 | [tool.hatch.build.hooks.pin_jumpstarter]
43 | name = "pin_jumpstarter"
44 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli-driver/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-cli-driver"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Nick Cao", email = "ncao@redhat.com" },
7 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
8 | { name = "Kirk Brauer", email = "kbrauer@hatci.com" },
9 | ]
10 | readme = "README.md"
11 | license = "Apache-2.0"
12 | requires-python = ">=3.11"
13 | dependencies = ["jumpstarter-cli-common", "click>=8.1.7.2"]
14 |
15 | [dependency-groups]
16 | dev = [
17 | "pytest>=8.3.2",
18 | "pytest-anyio>=0.0.0",
19 | "pytest-asyncio>=0.0.0",
20 | "pytest-cov>=5.0.0",
21 | ]
22 |
23 | [project.scripts]
24 | jmp-driver = "jumpstarter_cli_driver:driver"
25 |
26 | [tool.hatch.build.targets.wheel]
27 | packages = ["jumpstarter_cli_driver"]
28 |
29 | [tool.hatch.metadata.hooks.vcs.urls]
30 | Homepage = "https://jumpstarter.dev"
31 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
32 |
33 | [tool.hatch.version]
34 | source = "vcs"
35 | raw-options = { 'root' = '../../' }
36 |
37 | [build-system]
38 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
39 | build-backend = "hatchling.build"
40 |
41 | [tool.hatch.build.hooks.pin_jumpstarter]
42 | name = "pin_jumpstarter"
43 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-shell/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-shell"
3 | dynamic = ["version", "urls"]
4 | description = "Jumpstarter shell driver, for running controlled shell commands on the exporter."
5 | readme = "README.md"
6 | authors = [{ name = "Miguel Angel Ajo", email = "miguelangel@ajo.es" }]
7 | requires-python = ">=3.11"
8 | license = "Apache-2.0"
9 | dependencies = ["anyio>=4.10.0", "jumpstarter", "click>=8.1.8"]
10 |
11 | [project.entry-points."jumpstarter.drivers"]
12 | Shell = "jumpstarter_driver_shell.driver:Shell"
13 | [tool.pytest.ini_options]
14 | addopts = "--cov --cov-report=html --cov-report=xml"
15 | log_cli = true
16 | log_cli_level = "INFO"
17 | testpaths = ["jumpstarter_driver_shell"]
18 |
19 |
20 | [dependency-groups]
21 | dev = ["pytest-cov>=6.0.0", "pytest>=8.3.3"]
22 |
23 |
24 | [tool.hatch.metadata.hooks.vcs.urls]
25 | Homepage = "https://jumpstarter.dev"
26 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
27 |
28 | [tool.hatch.version]
29 | source = "vcs"
30 | raw-options = { 'root' = '../../' }
31 |
32 | [build-system]
33 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
34 | build-backend = "hatchling.build"
35 |
36 | [tool.hatch.build.hooks.pin_jumpstarter]
37 | name = "pin_jumpstarter"
38 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/ti_j784s4xevm/manifest.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: jumpstarter.dev/v1alpha1
2 | kind: FlashBundleManifest
3 | metadata:
4 | name: ti-j784s4
5 | spec:
6 | manufacturer: Texas Instruments
7 | link: "https://www.ti.com/tool/PROCESSOR-SDK-J784S4"
8 | bootcmd: "booti 0x82000000 - 0x84000000"
9 | shelltype: "busybox"
10 | login:
11 | login_prompt: "login:"
12 | username: "root"
13 | prompt: "#"
14 | default_target: "usd"
15 | targets:
16 | usd: "/sys/class/block#4fb0000"
17 | emmc: "/sys/class/block#4f80000"
18 | # removed for now, even if it's our documented procedure, if
19 | # the board is configured to boot from sd or emmc (and not SPI), and
20 | # the flashing of the final image fails, it will result in an un-bootable
21 | # system -> lab admin going to the site and re-flashing SD, this can
22 | # only be avoided by using something like sdwire
23 | #
24 | # preflash_commands:
25 | # - "dd if=/dev/zero of=/dev/mmcblk0 bs=512 count=34"
26 | # - "dd if=/dev/zero of=/dev/mmcblk1 bs=512 count=34"
27 | kernel:
28 | file: data/J784S4XEVM.flasher.img
29 | address: "0x82000000"
30 | dtb:
31 | default: k3-j784s4-evm
32 | address: "0x84000000"
33 | variants:
34 | k3-j784s4-evm:
35 | file: data/dtbs/k3-j784s4-evm.dtb
36 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/fabric.py:
--------------------------------------------------------------------------------
1 | from contextlib import asynccontextmanager
2 | from functools import partial
3 | from typing import Any
4 |
5 | from fabric.config import Config
6 | from fabric.connection import Connection
7 |
8 | from .portforward import handler
9 | from jumpstarter.client import DriverClient
10 | from jumpstarter.client.adapters import blocking
11 | from jumpstarter.common import TemporaryTcpListener
12 |
13 |
14 | @blocking
15 | @asynccontextmanager
16 | async def FabricAdapter(
17 | *,
18 | client: DriverClient,
19 | method: str = "connect",
20 | user: str | None = None,
21 | config: Config | None = None,
22 | forward_agent: bool | None = None,
23 | connect_timeout: int | None = None,
24 | connect_kwargs: dict[str, Any] | None = None,
25 | inline_ssh_env: bool | None = None,
26 | ):
27 | async with TemporaryTcpListener(partial(handler, client, method)) as addr:
28 | yield Connection(
29 | addr[0],
30 | user=user,
31 | port=addr[1],
32 | config=config,
33 | forward_agent=forward_agent,
34 | connect_timeout=connect_timeout,
35 | connect_kwargs=connect_kwargs,
36 | inline_ssh_env=inline_ssh_env,
37 | )
38 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver_test.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from jumpstarter_driver_tftp.driver import Tftp
4 |
5 | from jumpstarter.common.utils import serve
6 |
7 |
8 | @pytest.fixture
9 | def anyio_backend():
10 | return "asyncio"
11 |
12 |
13 | @pytest.fixture
14 | def tftp(tmp_path):
15 | with serve(Tftp(root_dir=str(tmp_path), host="127.0.0.1")) as client:
16 | try:
17 | yield client
18 | finally:
19 | client.close()
20 |
21 |
22 | @pytest.mark.anyio
23 | async def test_tftp_file_operations(tftp, tmp_path):
24 | filename = "test.txt"
25 | test_data = b"Hello"
26 |
27 | tftp.storage.write_bytes(filename, test_data)
28 |
29 | files = list(tftp.storage.list("/"))
30 | assert filename in files
31 |
32 | tftp.storage.delete(filename)
33 | assert filename not in list(tftp.storage.list("/"))
34 |
35 |
36 | def test_tftp_host_config(tmp_path):
37 | custom_host = "192.168.1.1"
38 | server = Tftp(root_dir=str(tmp_path), host=custom_host)
39 | assert server.get_host() == custom_host
40 |
41 |
42 | def test_tftp_root_directory_creation(tmp_path):
43 | new_dir = tmp_path / "new_tftp_root"
44 | server = Tftp(root_dir=str(new_dir))
45 | assert new_dir.exists()
46 | server.close()
47 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tftp/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-tftp"
3 | dynamic = ["version", "urls"]
4 | description = "Add your description here"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [{ name = "Benny Zlotnik", email = "bzlotnik@redhat.com" }]
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "anyio>=4.10.0",
11 | "jumpstarter",
12 | "jumpstarter-driver-composite",
13 | "jumpstarter-driver-opendal",
14 | ]
15 |
16 | [dependency-groups]
17 | dev = [
18 | "pytest>=8.3.2",
19 | "pytest-cov>=6.0.0",
20 | "pytest-anyio>=0.0.0",
21 | "pytest-asyncio>=0.0.0",
22 | "jumpstarter-testing",
23 | ]
24 |
25 |
26 | [tool.hatch.version]
27 | source = "vcs"
28 | raw-options = { 'root' = '../../' }
29 |
30 | [tool.hatch.metadata.hooks.vcs.urls]
31 | Homepage = "https://jumpstarter.dev"
32 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
33 |
34 | [tool.pytest.ini_options]
35 | log_cli = true
36 | log_cli_level = "INFO"
37 | testpaths = ["jumpstarter_driver_tftp"]
38 | asyncio_mode = "auto"
39 |
40 | [build-system]
41 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
42 | build-backend = "hatchling.build"
43 |
44 | [tool.hatch.build.hooks.pin_jumpstarter]
45 | name = "pin_jumpstarter"
46 |
--------------------------------------------------------------------------------
/assets/bolt.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/buildroot_defconfig:
--------------------------------------------------------------------------------
1 | # Initrd config
2 | BR2_aarch64=y
3 | BR2_TOOLCHAIN_EXTERNAL=y
4 | BR2_TARGET_GENERIC_HOSTNAME="flasher"
5 | BR2_TARGET_GENERIC_ISSUE="flasher"
6 | BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
7 | BR2_TARGET_GENERIC_ROOT_PASSWD=""
8 | BR2_SYSTEM_DHCP="eth0"
9 | BR2_ROOTFS_OVERLAY="$(CONFIG_DIR)/overlay"
10 | BR2_PACKAGE_CA_CERTIFICATES=y
11 | BR2_PACKAGE_OPENSSL=y
12 | BR2_PACKAGE_LIBCURL=y
13 | BR2_PACKAGE_LIBCURL_CURL=y
14 | BR2_PACKAGE_NTP=y
15 | BR2_PACKAGE_NTP_SNTP=y
16 | BR2_PACKAGE_NTP_NTPDATE=y
17 | BR2_TARGET_ROOTFS_CPIO=y
18 | BR2_TARGET_ROOTFS_CPIO_LZ4=y
19 | BR2_PACKAGE_DROPBEAR=n
20 | # use full-featured dd
21 | BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
22 | BR2_PACKAGE_COREUTILS=y
23 | # BR2_TARGET_ROOTFS_TAR is not set
24 | #
25 | #
26 | # Buildroot Kernel config
27 | # include initramfs within the kernel Image
28 | # on J784S4 the size exceeds uboot's CONFIG_SYS_BOOTM_LEN
29 | # BR2_TARGET_ROOTFS_INITRAMFS=y
30 | #
31 | # Not building kernel anymore, keeping for reference in case Fedora kernel is not good enough
32 | BR2_LINUX_KERNEL=n
33 | #BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y
34 | #BR2_LINUX_KERNEL_LZO=y
35 | #BR2_LINUX_KERNEL_IMAGE=y
36 | #BR2_LINUX_KERNEL_DTS_SUPPORT=y
37 | #BR2_LINUX_KERNEL_INTREE_DTS_NAME="ti/k3-j784s4-evm ti/k3-am69-sk"
38 |
39 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-yepkit/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-yepkit"
3 | dynamic = ["version", "urls"]
4 | description = "Add your description here"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [{ name = "Miguel Angel Ajo", email = "miguelangel@ajo.es" }]
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "anyio>=4.10.0",
11 | "pyusb>=1.2.1",
12 | "jumpstarter_driver_power",
13 | "jumpstarter",
14 | ]
15 |
16 | [project.entry-points."jumpstarter.drivers"]
17 | Ykush = "jumpstarter_driver_yepkit.driver:Ykush"
18 |
19 |
20 | [tool.hatch.version]
21 | source = "vcs"
22 | raw-options = { 'root' = '../../' }
23 |
24 | [tool.hatch.metadata.hooks.vcs.urls]
25 | Homepage = "https://jumpstarter.dev"
26 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
27 |
28 | [tool.pytest.ini_options]
29 | addopts = "--cov --cov-report=html --cov-report=xml"
30 | log_cli = true
31 | log_cli_level = "INFO"
32 | testpaths = ["jumpstarter_driver_yepkit"]
33 | asyncio_mode = "auto"
34 |
35 | [build-system]
36 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
37 | build-backend = "hatchling.build"
38 |
39 | [dependency-groups]
40 | dev = ["pytest-cov>=6.0.0", "pytest>=8.3.3"]
41 |
42 | [tool.hatch.build.hooks.pin_jumpstarter]
43 | name = "pin_jumpstarter"
44 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/common/condition.py:
--------------------------------------------------------------------------------
1 | # Ported from https://github.com/kubernetes/apimachinery/blob/v0.31.1/pkg/api/meta/conditions.go
2 |
3 | from jumpstarter_protocol import kubernetes_pb2
4 |
5 |
6 | def condition_present_and_equal(
7 | conditions: list[kubernetes_pb2.Condition], condition_type: str, status: str, reason: str | None = None
8 | ) -> bool:
9 | for condition in conditions:
10 | if condition.type == condition_type:
11 | if reason is None or condition.reason == reason:
12 | return condition.status == status
13 | return False
14 |
15 |
16 | def condition_message(
17 | conditions: list[kubernetes_pb2.Condition], condition_type: str, reason: str | None = None
18 | ) -> str | None:
19 | for condition in conditions:
20 | if condition.type == condition_type:
21 | if reason is None or condition.reason == reason:
22 | return condition.message
23 | return None
24 |
25 |
26 | def condition_true(conditions: list[kubernetes_pb2.Condition], condition_type: str) -> bool:
27 | return condition_present_and_equal(conditions, condition_type, "True")
28 |
29 |
30 | def condition_false(conditions: list[kubernetes_pb2.Condition], condition_type: str) -> bool:
31 | return condition_present_and_equal(conditions, condition_type, "False")
32 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-uboot/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-uboot"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Nick Cao", email = "ncao@redhat.com" },
7 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
8 | { name = "Kirk Brauer", email = "kbrauer@hatci.com" },
9 | ]
10 | readme = "README.md"
11 | license = "Apache-2.0"
12 | requires-python = ">=3.11"
13 | dependencies = ["jumpstarter", "jumpstarter-driver-composite", "pexpect>=4.9.0"]
14 |
15 | [dependency-groups]
16 | dev = [
17 | "jumpstarter-driver-qemu",
18 | "pytest>=8.3.2",
19 | "pytest-cov>=5.0.0",
20 | "requests>=2.32.3",
21 | "rpmfile>=2.1.0",
22 | "zstandard>=0.23.0",
23 | ]
24 |
25 | [tool.hatch.metadata.hooks.vcs.urls]
26 | Homepage = "https://jumpstarter.dev"
27 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
28 |
29 | [tool.hatch.version]
30 | source = "vcs"
31 | raw-options = { 'root' = '../../' }
32 |
33 | [tool.uv.sources]
34 | jumpstarter-driver-composite = { workspace = true }
35 | jumpstarter-driver-qemu = { workspace = true }
36 |
37 | [build-system]
38 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
39 | build-backend = "hatchling.build"
40 |
41 | [tool.hatch.build.hooks.pin_jumpstarter]
42 | name = "pin_jumpstarter"
43 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-cli"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Nick Cao", email = "ncao@redhat.com" },
7 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
8 | { name = "Kirk Brauer", email = "kbrauer@hatci.com" },
9 | ]
10 | readme = "README.md"
11 | license = "Apache-2.0"
12 | requires-python = ">=3.11"
13 | dependencies = [
14 | "jumpstarter-cli-admin",
15 | "jumpstarter-cli-driver",
16 | "pytimeparse2>=1.7.1",
17 | ]
18 |
19 | [dependency-groups]
20 | dev = [
21 | "pytest>=8.3.2",
22 | "pytest-anyio>=0.0.0",
23 | "pytest-asyncio>=0.0.0",
24 | "pytest-cov>=5.0.0",
25 | ]
26 |
27 | [project.scripts]
28 | jmp = "jumpstarter_cli.jmp:jmp"
29 | j = "jumpstarter_cli.j:j"
30 |
31 | [tool.hatch.build.targets.wheel]
32 | packages = ["jumpstarter_cli"]
33 |
34 | [tool.hatch.metadata.hooks.vcs.urls]
35 | Homepage = "https://jumpstarter.dev"
36 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
37 |
38 | [tool.hatch.version]
39 | source = "vcs"
40 | raw-options = { 'root' = '../../' }
41 |
42 | [build-system]
43 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
44 | build-backend = "hatchling.build"
45 |
46 | [tool.hatch.build.hooks.pin_jumpstarter]
47 | name = "pin_jumpstarter"
48 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/novnc_test.py:
--------------------------------------------------------------------------------
1 | from contextlib import closing
2 | from urllib.parse import parse_qsl, urlparse
3 |
4 | from anyio.from_thread import start_blocking_portal
5 | from websocket import create_connection
6 |
7 | from ..driver import TcpNetwork
8 | from .novnc import NovncAdapter
9 | from jumpstarter.common import TemporaryTcpListener
10 | from jumpstarter.common.utils import serve
11 |
12 |
13 | async def echo_handler(stream):
14 | async with stream:
15 | while True:
16 | try:
17 | await stream.send(await stream.receive())
18 | except Exception:
19 | pass
20 |
21 |
22 | def test_client_adapter_novnc():
23 | with start_blocking_portal() as portal:
24 | with portal.wrap_async_context_manager(TemporaryTcpListener(echo_handler, local_host="127.0.0.1")) as addr:
25 | with serve(TcpNetwork(host=addr[0], port=addr[1])) as client:
26 | with NovncAdapter(client=client) as url:
27 | parsed = dict(parse_qsl(urlparse(url).query))
28 | with closing(create_connection(f"ws://{parsed['host']}:{parsed['port']}")) as ws:
29 | ws.ping()
30 | ws.send_bytes(b"hello")
31 | assert ws.recv() == b"hello"
32 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ssh/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-ssh"
3 | dynamic = ["version", "urls"]
4 | description = "SSH wrapper driver for Jumpstarter that provides SSH CLI functionality"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [
8 | { name = "Miguel Angel Ajo Pelayo", email = "miguelangel@ajo.es" }
9 | ]
10 | requires-python = ">=3.11"
11 | dependencies = [
12 | "anyio>=4.10.0",
13 | "click>=8.0.0",
14 | "jumpstarter",
15 | "jumpstarter-driver-composite",
16 | "jumpstarter-driver-network",
17 | ]
18 |
19 | [tool.hatch.version]
20 | source = "vcs"
21 | raw-options = { 'root' = '../../'}
22 |
23 | [tool.hatch.metadata.hooks.vcs.urls]
24 | Homepage = "https://jumpstarter.dev"
25 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
26 |
27 | [tool.pytest.ini_options]
28 | addopts = "--cov --cov-report=html --cov-report=xml"
29 | log_cli = true
30 | log_cli_level = "INFO"
31 | testpaths = ["jumpstarter_driver_ssh"]
32 | asyncio_mode = "auto"
33 |
34 | [build-system]
35 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
36 | build-backend = "hatchling.build"
37 |
38 | [tool.hatch.build.hooks.pin_jumpstarter]
39 | name = "pin_jumpstarter"
40 |
41 | [dependency-groups]
42 | dev = [
43 | "pytest-cov>=6.0.0",
44 | "pytest>=8.3.3",
45 | ]
46 |
--------------------------------------------------------------------------------
/packages/jumpstarter/jumpstarter/streams/metadata.py:
--------------------------------------------------------------------------------
1 | from contextlib import suppress
2 | from dataclasses import dataclass
3 | from typing import Any, Callable, Mapping
4 |
5 | from anyio import TypedAttributeLookupError, TypedAttributeSet, typed_attribute
6 | from anyio.abc import AnyByteStream, ObjectStream
7 |
8 |
9 | class MetadataStreamAttributes(TypedAttributeSet):
10 | # https://grpc.io/docs/guides/metadata/
11 | metadata: dict[str, str] = typed_attribute()
12 |
13 |
14 | @dataclass(frozen=True, kw_only=True, slots=True)
15 | class MetadataStream(ObjectStream[bytes]):
16 | stream: AnyByteStream
17 | metadata: dict[str, str]
18 |
19 | async def send(self, item: bytes):
20 | await self.stream.send(item)
21 |
22 | async def receive(self) -> bytes:
23 | return await self.stream.receive()
24 |
25 | async def send_eof(self):
26 | await self.stream.send_eof()
27 |
28 | async def aclose(self):
29 | await self.stream.aclose()
30 |
31 | @property
32 | def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]:
33 | metadata = {}
34 | with suppress(TypedAttributeLookupError):
35 | metadata = self.stream.extra(MetadataStreamAttributes.metadata)
36 | return self.stream.extra_attributes | {MetadataStreamAttributes.metadata: lambda: metadata | self.metadata}
37 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-gpiod/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-gpiod"
3 | dynamic = ["version", "urls"]
4 | description = ""
5 | authors = [
6 | { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" },
7 | { name = "Nick Cao", email = "ncao@redhat.com" },
8 | { name = "Kirk Brauer", email = "kbrauer@hatci.com" },
9 | ]
10 | readme = "README.md"
11 | license = "Apache-2.0"
12 | requires-python = ">=3.11"
13 | dependencies = ["jumpstarter", "jumpstarter-driver-power", "click>=8.1.7.2", "gpiod; platform_system == 'Linux'"]
14 |
15 | [project.entry-points."jumpstarter.drivers"]
16 | DigitalInput = "jumpstarter_driver_gpiod.driver:DigitalInput"
17 | DigitalOutput = "jumpstarter_driver_gpiod.driver:DigitalOutput"
18 | PowerSwitch = "jumpstarter_driver_gpiod.driver:PowerSwitch"
19 |
20 | [dependency-groups]
21 | dev = ["pytest>=8.3.2", "pytest-cov>=5.0.0"]
22 |
23 | [tool.hatch.metadata.hooks.vcs.urls]
24 | Homepage = "https://jumpstarter.dev"
25 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
26 |
27 | [tool.hatch.version]
28 | source = "vcs"
29 | raw-options = { 'root' = '../../' }
30 |
31 | [build-system]
32 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
33 | build-backend = "hatchling.build"
34 |
35 | [tool.hatch.build.hooks.pin_jumpstarter]
36 | name = "pin_jumpstarter"
37 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-ridesx/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-ridesx"
3 | dynamic = ["version", "urls"]
4 | description = "Jumpstarter driver for Qualcomm RideSX"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [{ name = "Benny Zlotnik", email = "bzlotnik@redhat.com" }]
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "jumpstarter",
11 | "jumpstarter-driver-composite",
12 | "jumpstarter-driver-opendal",
13 | "jumpstarter-driver-power",
14 | "jumpstarter-driver-pyserial",
15 | ]
16 |
17 | [tool.hatch.version]
18 | source = "vcs"
19 | raw-options = { 'root' = '../../' }
20 |
21 | [tool.hatch.metadata.hooks.vcs.urls]
22 | Homepage = "https://jumpstarter.dev"
23 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
24 |
25 | [tool.pytest.ini_options]
26 | addopts = "--cov --cov-report=html --cov-report=xml"
27 | log_cli = true
28 | log_cli_level = "INFO"
29 | testpaths = ["jumpstarter_driver_ridesx"]
30 | asyncio_mode = "auto"
31 |
32 |
33 | [build-system]
34 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
35 | build-backend = "hatchling.build"
36 |
37 | [dependency-groups]
38 | dev = [
39 | "pytest-cov>=6.0.0",
40 | "pytest>=8.3.3",
41 | "pytest-asyncio>=0.0.0",
42 | ]
43 |
44 | [tool.hatch.build.hooks.pin_jumpstarter]
45 | name = "pin_jumpstarter"
46 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-snmp/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-snmp"
3 | dynamic = ["version", "urls"]
4 | description = "SNMP driver"
5 | readme = "README.md"
6 | requires-python = ">=3.11"
7 | license = "Apache-2.0"
8 | authors = [{ name = "Benny Zlotnik", email = "bzlotnik@redhat.com" }]
9 |
10 | dependencies = [
11 | "click>=8.1.8",
12 | "jumpstarter",
13 | "jumpstarter-driver-power",
14 | "pysnmp==7.1.16",
15 | ]
16 |
17 |
18 | [dependency-groups]
19 | dev = [
20 | "pytest>=8.3.2",
21 | "pytest-cov>=6.0.0",
22 | "pytest-anyio>=0.0.0",
23 | "pytest-asyncio>=0.0.0",
24 | "jumpstarter-testing",
25 | ]
26 |
27 |
28 | [tool.pytest.ini_options]
29 | log_cli = true
30 | log_cli_level = "INFO"
31 | testpaths = ["jumpstarter_driver_snmp"]
32 | asyncio_mode = "auto"
33 |
34 | [tool.hatch.metadata.hooks.vcs.urls]
35 | Homepage = "https://jumpstarter.dev"
36 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
37 |
38 | [tool.hatch.version]
39 | source = "vcs"
40 | raw-options = { 'root' = '../../' }
41 |
42 | [build-system]
43 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
44 | build-backend = "hatchling.build"
45 |
46 | [tool.hatch.build.hooks.pin_jumpstarter]
47 | name = "pin_jumpstarter"
48 |
49 | [tool.uv.sources]
50 | jumpstarter-driver-power = { workspace = true }
51 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-vnc/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-vnc"
3 | dynamic = ["version", "urls"]
4 | description = "Jumpstarter driver for VNC"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [
8 | { name = "Albert Esteve", email = "aesteve@redhat.com" }
9 | ]
10 | requires-python = ">=3.11"
11 | dependencies = [
12 | "anyio>=4.10.0",
13 | "jumpstarter",
14 | "jumpstarter-driver-composite",
15 | "jumpstarter-driver-network",
16 | "click",
17 | ]
18 |
19 | [project.entry-points."jumpstarter.drivers"]
20 | vnc = "jumpstarter_driver_vnc.driver:Vnc"
21 |
22 | [tool.hatch.version]
23 | source = "vcs"
24 | raw-options = { 'root' = '../../'}
25 |
26 | [tool.hatch.metadata.hooks.vcs.urls]
27 | Homepage = "https://jumpstarter.dev"
28 | source_archive = "https://github.com/jumpstarter-dev/jumpstarter/archive/{commit_hash}.zip"
29 |
30 | [tool.pytest.ini_options]
31 | addopts = "--cov --cov-report=html --cov-report=xml"
32 | log_cli = true
33 | log_cli_level = "INFO"
34 | testpaths = ["jumpstarter_driver_vnc"]
35 | asyncio_mode = "auto"
36 |
37 | [build-system]
38 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
39 | build-backend = "hatchling.build"
40 |
41 | [tool.hatch.build.hooks.pin_jumpstarter]
42 | name = "pin_jumpstarter"
43 |
44 | [dependency-groups]
45 | dev = [
46 | "pytest-cov>=6.0.0",
47 | "pytest>=8.3.3",
48 | ]
49 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/portforward.py:
--------------------------------------------------------------------------------
1 | from contextlib import asynccontextmanager
2 | from functools import partial
3 | from os import PathLike
4 |
5 | from jumpstarter.client import DriverClient
6 | from jumpstarter.client.adapters import blocking
7 | from jumpstarter.common import TemporaryTcpListener, TemporaryUnixListener
8 | from jumpstarter.streams.common import forward_stream
9 |
10 |
11 | async def handler(client, method, conn):
12 | async with conn:
13 | async with client.stream_async(method) as stream:
14 | async with forward_stream(conn, stream):
15 | pass
16 |
17 |
18 | @blocking
19 | @asynccontextmanager
20 | async def TcpPortforwardAdapter(
21 | *,
22 | client: DriverClient,
23 | method: str = "connect",
24 | local_host: str = "127.0.0.1",
25 | local_port: int = 0,
26 | ):
27 | async with TemporaryTcpListener(
28 | partial(handler, client, method),
29 | local_host=local_host,
30 | local_port=local_port,
31 | ) as addr:
32 | yield addr
33 |
34 |
35 | @blocking
36 | @asynccontextmanager
37 | async def UnixPortforwardAdapter(
38 | *,
39 | client: DriverClient,
40 | method: str = "connect",
41 | path: PathLike | None = None,
42 | ):
43 | async with TemporaryUnixListener(partial(handler, client, method), path=path) as addr:
44 | yield addr
45 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/build_fits.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cd "$(dirname "$0")"
4 |
5 | # run only in a container
6 | if [[ -z "$container" && ! -f /.dockerenv ]]; then
7 | exec podman run --rm -it -v $(pwd):/host:Z -w /host fedora:42 "$0" "$@"
8 | else
9 | set -euo pipefail
10 | BUILDROOT_DIR="/var/tmp/buildroot"
11 |
12 | dnf install --setopt=install_weak_deps=false -y git make gcc gcc-c++ which file diffutils \
13 | wget cpio rsync bc lzop zip patch perl tar qemu-system-aarch64 qemu-img unzboot \
14 | uboot-tools kmod awk zstd lz4 kernel dtc rpm-build
15 |
16 | git clone --depth 1 --branch 2025.08 https://github.com/buildroot/buildroot "${BUILDROOT_DIR}"
17 |
18 | # build buildroot (initramfs)
19 | cp buildroot_defconfig "${BUILDROOT_DIR}/configs/"
20 | cp -R overlay "${BUILDROOT_DIR}"
21 | ./kernel_fedora.sh "${BUILDROOT_DIR}/overlay"
22 | ( cd "${BUILDROOT_DIR}"; make buildroot_defconfig && make )
23 | dtc s32g3.dts -o s32g3.dtb
24 | mkimage -f fedora.its data/flasher-fedora.itb
25 | rm -rf "${BUILDROOT_DIR}/overlay"
26 |
27 | # replace kernel with kernel-automotive and rebuild. Beware the $BUILDROOT_DIR/output/target is reused!
28 | cp -R overlay "${BUILDROOT_DIR}"
29 | ./kernel_automotive.sh "${BUILDROOT_DIR}/overlay"
30 | ( cd "${BUILDROOT_DIR}" && make )
31 | mkimage -f automotive.its data/flasher-automotive.itb
32 | rm -rf "${BUILDROOT_DIR}/overlay"
33 | fi
34 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-tasmota/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "jumpstarter-driver-tasmota"
3 | dynamic = ["version", "urls"]
4 | description = "Jumpstarter driver for controlling Tasmota-compatible devices via MQTT"
5 | readme = "README.md"
6 | license = "Apache-2.0"
7 | authors = [{ name = "Nick Cao", email = "nickcao@nichi.co" }]
8 | requires-python = ">=3.11"
9 | dependencies = [
10 | "anyio>=4.10.0",
11 | "jumpstarter_driver_power",
12 | "jumpstarter",
13 | "paho-mqtt>=2.1.0",
14 | ]
15 |
16 | [project.entry-points."jumpstarter.drivers"]
17 | TasmotaPower = "jumpstarter_driver_tasmota.driver:TasmotaPower"
18 |
19 |
20 | [tool.hatch.version]
21 | source = "vcs"
22 | raw-options = { 'root' = '../../' }
23 |
24 | [tool.hatch.metadata.hooks.vcs.urls]
25 | Homepage = "https://jumpstarter.dev"
26 | source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip"
27 |
28 | [tool.pytest.ini_options]
29 | addopts = "--cov --cov-report=html --cov-report=xml"
30 | log_cli = true
31 | log_cli_level = "INFO"
32 | testpaths = ["jumpstarter_driver_tasmota"]
33 |
34 | [build-system]
35 | requires = ["hatchling", "hatch-vcs", "hatch-pin-jumpstarter"]
36 | build-backend = "hatchling.build"
37 |
38 | [tool.hatch.build.hooks.pin_jumpstarter]
39 | name = "pin_jumpstarter"
40 |
41 | [dependency-groups]
42 | dev = [
43 | "pytest-cov>=6.0.0",
44 | "pytest>=8.3.3",
45 | "pytest-mqtt>=0.5.0",
46 | ]
47 |
--------------------------------------------------------------------------------
/packages/jumpstarter-driver-vnc/jumpstarter_driver_vnc/driver.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from dataclasses import dataclass
4 |
5 | from jumpstarter_driver_composite.driver import Composite
6 |
7 | from jumpstarter.common.exceptions import ConfigurationError
8 | from jumpstarter.driver import export
9 |
10 |
11 | @dataclass
12 | class Vnc(Composite):
13 | """A VNC driver.
14 |
15 | Members:
16 | default_encrypt: Whether to default to an encrypted client connection.
17 | """
18 |
19 | default_encrypt: bool = False
20 |
21 | def __post_init__(self):
22 | """
23 | Validate the VNC driver's post-initialization configuration.
24 | Ensures the driver has a "tcp" child configured.
25 |
26 | Raises:
27 | ConfigurationError: If a "tcp" child is not present.
28 | """
29 | super().__post_init__()
30 | if "tcp" not in self.children:
31 | raise ConfigurationError("A tcp child is required for Vnc")
32 |
33 | @export
34 | async def get_default_encrypt(self) -> bool:
35 | """Return the default encryption setting."""
36 | return self.default_encrypt
37 |
38 | @classmethod
39 | def client(cls) -> str:
40 | """
41 | Client class path for this driver.
42 |
43 | Returns:
44 | str: Dotted import path of the client class.
45 | """
46 | return "jumpstarter_driver_vnc.client.VNClient"
47 |
--------------------------------------------------------------------------------
/packages/jumpstarter-cli/jumpstarter_cli/update.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime, timedelta
2 |
3 | import click
4 | from jumpstarter_cli_common.config import opt_config
5 | from jumpstarter_cli_common.exceptions import handle_exceptions_with_reauthentication
6 | from jumpstarter_cli_common.opt import OutputType, opt_output_all
7 | from jumpstarter_cli_common.print import model_print
8 |
9 | from .common import opt_begin_time, opt_duration_partial
10 | from .login import relogin_client
11 |
12 |
13 | @click.group()
14 | def update():
15 | """
16 | Update a resource
17 | """
18 |
19 |
20 | @update.command(name="lease")
21 | @opt_config(exporter=False)
22 | @click.argument("name")
23 | @opt_duration_partial(required=False)
24 | @opt_begin_time
25 | @opt_output_all
26 | @handle_exceptions_with_reauthentication(relogin_client)
27 | def update_lease(config, name: str, duration: timedelta | None, begin_time: datetime | None, output: OutputType):
28 | """
29 | Update a lease
30 |
31 | Update the duration and/or begin time of an existing lease.
32 | At least one of --duration or --begin-time must be specified.
33 | Updating the begin time of an already active lease is not allowed.
34 | """
35 |
36 | if duration is None and begin_time is None:
37 | raise click.UsageError("At least one of --duration or --begin-time must be specified")
38 |
39 | lease = config.update_lease(name, duration=duration, begin_time=begin_time)
40 |
41 | model_print(lease, output)
42 |
--------------------------------------------------------------------------------