Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Handlers/argParseHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def __init__(self, test_data):
parser.add_argument('--buildurl', type=str, help='custom build json url')
parser.add_argument('--localjson', type=str, help='local json parsing')
parser.add_argument('--template', type=str, help='For parsing local path or web url for template')
parser.add_argument('--meta-qcom', action='store_true', help='Enable meta-qcom specific auto-login for flasher boot method')
logging.debug('Added optional arguments')

if self.test_data is not None:
Expand Down Expand Up @@ -63,3 +64,8 @@ def get_template_path(self):
template_path = self.argument.template
logging.debug(f'Template path: {template_path}')
return template_path

def is_meta_qcom_enabled(self):
meta_qcom_enabled = self.argument.meta_qcom
logging.debug(f'Meta-qcom enabled: {meta_qcom_enabled}')
return meta_qcom_enabled
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ cd job_render
# Usage

- Set environment variables (BOOT_METHOD, TARGET, TARGET_DTB) in your shell before running the script using the export command.
Supported `BOOT_METHOD` values: `fastboot`, `u-boot`, `efi`, `flasher`.
When using `BOOT_METHOD=efi` or `BOOT_METHOD=flasher`, set `FLASH_IMAGE` (required) and optionally `FLASH_PORT`.
For `BOOT_METHOD=flasher`, pass `--meta-qcom` to enable the `auto_login` block (login prompt `login:`, user `root`).
Example:
```
export BOOT_METHOD="fastboot"
Expand All @@ -33,4 +36,3 @@ export TARGET_DTB="qcs6490-rb3gen2"
# License

job_render is licensed under the [*BSD-3-clause-clear License*](https://spdx.org/licenses/BSD-3-Clause-Clear.html). See [*LICENSE*](https://github.com/qualcomm-linux/job_render/blob/main/LICENSE) for the full license text.

3 changes: 2 additions & 1 deletion data/cloudData.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"modules": "",
"kselftest_tar_gz": "https://files.kernelci.org/kbuild-gcc-12-arm64-681a3b1cea9ae9de13450f99/kselftest.tar.gz",
"ramdisk": "",
"firmware": ""
"firmware": "",
"flash_image": ""
},
"data": {
"kernel_revision": {
Expand Down
9 changes: 6 additions & 3 deletions data_validation/validate_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys

# Allowed boot methods
allowed_boot_methods = ['fastboot', 'u-boot']
allowed_boot_methods = ['fastboot', 'u-boot', 'efi', 'flasher']


class Validator:
Expand All @@ -23,7 +23,10 @@ def validate_platform_config(self):
# Check if boot_method is valid
if self.platform_config['boot_method'] not in allowed_boot_methods:
return False, f"Invalid boot_method: {self.platform_config['boot_method']}. Allowed values are {allowed_boot_methods},use export command to set environment variables"


if self.platform_config['boot_method'] == 'efi' and not self.platform_config.get('flash_image'):
return False, "BOOT_METHOD 'efi' requires FLASH_IMAGE to be set"

return True, "Valid platform_config"


Expand Down Expand Up @@ -57,4 +60,4 @@ def perform_validations_and_proceed(self):
sys.exit(1)
except Exception as e:
print(f"An unexpected error occurred: {e}")
sys.exit(1)
sys.exit(1)
14 changes: 11 additions & 3 deletions lava_Job_definition_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,19 @@
boot_method = os.environ.get("BOOT_METHOD")
name = os.environ.get("TARGET")
target_dtb = os.environ.get("TARGET_DTB")
flash_image = os.environ.get("FLASH_IMAGE")
flash_port = os.environ.get("FLASH_PORT", "0")
brarch = 'arm64'


# Create logs directory if it doesn't exist
if not os.path.exists('logs'):
os.makedirs('logs')

# Create renders directory if it doesn't exist
if not os.path.exists('renders'):
os.makedirs('renders')


# Generate a unique log file name based on the current timestamp
log_filename = datetime.now().strftime('logs/log_%Y%m%d_%H%M%S.log')
Expand All @@ -35,7 +41,8 @@

platform_config = {
'boot_method': boot_method,
'name': name
'name': name,
'flash_image': flash_image
}
# Example test method,
# → picks the value from the environment if it exists
Expand Down Expand Up @@ -67,6 +74,7 @@
is_buildurl_provided = arg_parse_handler.get_buildurl()
local_json_path = arg_parse_handler.get_local_json_path()
template_path = arg_parse_handler.get_template_path()
meta_qcom_enabled = arg_parse_handler.is_meta_qcom_enabled()

### Error Handling for more than one arguments for json passing (options: build_url, node_id, localjson)
class ConflictError(Exception):
Expand Down Expand Up @@ -129,7 +137,7 @@ class ConflictError(Exception):

### Render the template with dynamic data
node_data = data_handler.get_fetched_data()
job_definition = template_handler.render_template(template, node=data_handler.get_fetched_data(), platform_config=platform_config, test_method=test_method, tests_count=data_handler.get_count_of_tests(),device_dtb = node_data['artifacts']['dtb'],brarch=brarch)
job_definition = template_handler.render_template(template, node=data_handler.get_fetched_data(), platform_config=platform_config, test_method=test_method, tests_count=data_handler.get_count_of_tests(), device_dtb=node_data['artifacts']['dtb'], brarch=brarch, flash_port=flash_port, meta_qcom=meta_qcom_enabled)

# Parse the rendered YAML and Save the rendered job definition
template_handler.save_rendered_template(job_definition, os.path.join('renders','lava_job_definition.yaml'))
template_handler.save_rendered_template(job_definition, os.path.join('renders','lava_job_definition.yaml'))
84 changes: 84 additions & 0 deletions templates/boot/efi.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{%- set flash_image_url = flash_image_url | default(platform_config.flash_image, true) -%}
{%- if flash_image_name is not defined and flash_image_url -%}
{%- set flash_image_name = flash_image_url.split('/')[-1] -%}
{%- endif -%}

- deploy:
images:
image:
{% if flash_image_headers %}
headers:
{% for key, value in flash_image_headers.items() %}
{{ key }}: '{{ value }}'
{% endfor %}
{% endif %}
url: '{{ flash_image_url }}'
dtb:
url: '{{ node.artifacts.dtb }}'
kernel:
url: '{{ node.artifacts.kernel }}'
ramdisk:
{% if boot_commands == "ramdisk" %}
url: '{{ ramdiskroot }}/rootfs.cpio.gz'
{% else %}
url: 'https://storage.kernelci.org/images/rootfs/debian/bookworm-kselftest/20250724.0/{{ brarch }}/initrd.cpio.gz'
{% endif %}
compression: gz
format: cpio.newc
overlays:
lava: true
{% filter indent(width=10) %}
{% block testoverlays %}{% endblock %}
{% endfilter %}
{% set dtb = device_dtb.split('/')[-1] %}
{% if boot_commands == "ramdisk" %}
{% set ramdisk_name = "rootfs.cpio.gz" %}
{% else %}
{% set ramdisk_name = "initrd.cpio.gz" %}
{% endif %}
postprocess:
docker:
image: ghcr.io/nandini-matam/kmake-image:v5
steps:
{%- if node.data.kernel_type.endswith('.gz') %}
- gunzip Image.gz
{%- endif %}
- generate_boot_bins.sh efi --ramdisk {{ ramdisk_name }} --systemd-boot /artifacts/systemd/usr/lib/systemd/boot/efi/systemd-bootaa64.efi --stub /artifacts/systemd/usr/lib/systemd/boot/efi/linuxaa64.efi.stub --linux Image --cmdline "console=ttyMSM0,115200n8 copy-modules rootdelay=10 root=PARTLABEL=rootfs rw rootwait qcom_geni_serial.con_enabled=1" --output images
- generate_boot_bins.sh dtb --input {{ dtb }} --output images
- export IMAGE_PATH=$PWD
- cp overlay*.tar.gz overlay.tar.gz
- echo "OVERLAY=overlay.tar.gz" >> $IMAGE_PATH/flash.settings
- echo "OVERLAY_PATH=/" >> $IMAGE_PATH/flash.settings
- echo "ROOTFS_IMAGE=rootfs.img" >> $IMAGE_PATH/flash.settings
- echo "EFI=images/efi.bin" >> $IMAGE_PATH/flash.settings
- echo "DTB=images/dtb.bin" >> $IMAGE_PATH/flash.settings
- echo "DEVICE_TYPE={{ platform_config.name }}" >> $IMAGE_PATH/flash.settings
- echo "PORT={{ flash_port | default('0', true) }}" >> $IMAGE_PATH/flash.settings
- cat $IMAGE_PATH/flash.settings
timeout:
minutes: 60
to: downloads

- deploy:
to: flasher
images:
image:
url: 'downloads://{{ flash_image_name }}'
settings:
url: 'downloads://flash.settings'
overlay:
url: 'downloads://overlay.tar.gz'
timeout:
minutes: 15
- boot:
prompts:
- '/ #'
failure_retry: 3
timeout:
minutes: 10
timeouts:
bootloader-commands:
minutes: 5
auto-login-action:
minutes: 5
method: minimal
53 changes: 53 additions & 0 deletions templates/boot/flasher.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
- deploy:
images:
image:
url: '{{ node.artifacts.flash_image }}'
postprocess:
docker:
image: ghcr.io/mwasilew/docker-mkbootimage:master
steps:
- export IMAGE_PATH=$PWD
- cp overlay*.tar.gz overlay.tar.gz
- echo "OVERLAY=overlay.tar.gz" >> $IMAGE_PATH/flash.settings
- echo "OVERLAY_PATH=/" >> $IMAGE_PATH/flash.settings
- echo "ROOTFS_IMAGE=rootfs.img" >> $IMAGE_PATH/flash.settings
- echo "DEVICE_TYPE={{ platform_config.name }}" >> $IMAGE_PATH/flash.settings
- echo "PORT=0" >> $IMAGE_PATH/flash.settings
- cat $IMAGE_PATH/flash.settings
timeout:
minutes: 30
to: downloads
{% set flash_image_url = node.artifacts.flash_image %}
{% set flash_image_path = flash_image_url.split('?')[0] %}
{% set flash_image_name = flash_image_path.split('/')[-1] %}
- deploy:
images:
image:
url: 'downloads://{{ flash_image_name }}'
settings:
url: downloads://flash.settings
overlay:
url: downloads://overlay.tar.gz
timeout:
minutes: 10
to: flasher
- boot:
{% if meta_qcom | default(false, true) %}
auto_login:
login_prompt: 'login:'
username: root
password_prompt: Password
password: oelinux123
{% endif %}
prompts:
- root@{{ platform_config.name }}
- root@(.*):[/~]#
failure_retry: 3
timeout:
minutes: 10
timeouts:
bootloader-commands:
minutes: 3
auto-login-action:
minutes: 10
method: minimal
Loading