summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Williams <neil.williams@linaro.org>2014-10-07 15:32:18 (GMT)
committerNeil Williams <neil.williams@linaro.org>2014-10-07 15:32:18 (GMT)
commit8d2aa71558f46d982839c7b03017de426e3c1398 (patch)
tree8c431c150192237d863a04f177217cad68f4df40
parent1f905e5882c8079090473c2c9b91ce5bef2aca5e (diff)
parent1ef33872730b3a73ca49b32e34f66a8c6dc98b99 (diff)
downloadlava-dispatcher-8d2aa71558f46d982839c7b03017de426e3c1398.tar.gz
lava-dispatcher-8d2aa71558f46d982839c7b03017de426e3c1398.tar.xz
Merge branch 'staging' into release
-rw-r--r--lava_dispatcher/actions/lmp/init_boards.py61
-rw-r--r--lava_dispatcher/config.py49
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/amarillo.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/arndale-octa.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/arndale.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/b2120stxh407.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/beagle-xm.conf4
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone-black.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/cubieboard3.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/d01.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/ifc6410.conf1
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/imx6q-wandboard.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/juno.conf (renamed from lava_dispatcher/default-config/lava-dispatcher/device-types/wg.conf)236
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/keystone.conf15
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/mcdivitt.conf42
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/mustang.conf3
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/panda-es.conf3
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/panda.conf3
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base-aemv8a.conf3
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x1-a53x1.conf3
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x4-a53x4.conf3
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x1-a7x1.conf20
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x4-a7x4.conf20
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-armv8.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/snowball.conf9
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/stx7108.conf2
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/utilite-pro.conf37
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-a5.conf151
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-a9.conf151
-rw-r--r--lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-tc2.conf145
-rw-r--r--lava_dispatcher/device/bootloader.py29
-rw-r--r--lava_dispatcher/device/fastboot.py10
-rw-r--r--lava_dispatcher/device/fastboot_drivers.py6
-rw-r--r--lava_dispatcher/device/fastmodel.py39
-rw-r--r--lava_dispatcher/device/ipmi_tftp.py3
-rw-r--r--lava_dispatcher/device/jtag_drivers.py6
-rw-r--r--lava_dispatcher/device/master.py14
-rw-r--r--lava_dispatcher/device/target.py3
-rw-r--r--lava_dispatcher/device/vexpress.py158
-rw-r--r--lava_dispatcher/device/wg.py225
-rw-r--r--lava_dispatcher/downloader.py21
-rw-r--r--lava_dispatcher/job.py13
-rw-r--r--lava_dispatcher/pipeline/action.py231
-rw-r--r--lava_dispatcher/pipeline/actions/boot/__init__.py9
-rw-r--r--lava_dispatcher/pipeline/actions/boot/kvm.py131
-rw-r--r--lava_dispatcher/pipeline/actions/deploy/image.py9
-rw-r--r--lava_dispatcher/pipeline/actions/deploy/mount.py13
-rw-r--r--lava_dispatcher/pipeline/actions/deploy/overlay.py72
-rw-r--r--lava_dispatcher/pipeline/actions/deploy/testdef.py184
-rw-r--r--lava_dispatcher/pipeline/actions/test/__init__.py20
-rw-r--r--lava_dispatcher/pipeline/device.py36
-rw-r--r--lava_dispatcher/pipeline/device_types/kvm.conf17
-rw-r--r--lava_dispatcher/pipeline/devices/kvm01.conf2
-rw-r--r--lava_dispatcher/pipeline/job.py10
-rw-r--r--lava_dispatcher/pipeline/parser.py20
-rw-r--r--lava_dispatcher/pipeline/serial.py39
-rw-r--r--lava_dispatcher/pipeline/shell.py144
-rw-r--r--lava_dispatcher/pipeline/test/sample_jobs/basics.yaml2
-rw-r--r--lava_dispatcher/pipeline/test/sample_jobs/kvm.yaml2
-rw-r--r--lava_dispatcher/pipeline/test/test_basic.py2
-rw-r--r--lava_dispatcher/pipeline/test/test_defs.py12
-rw-r--r--lava_dispatcher/pipeline/test/test_job.py5
-rw-r--r--lava_dispatcher/utils.py49
64 files changed, 1964 insertions, 553 deletions
diff --git a/lava_dispatcher/actions/lmp/init_boards.py b/lava_dispatcher/actions/lmp/init_boards.py
index 6578e11..20a4c8e 100644
--- a/lava_dispatcher/actions/lmp/init_boards.py
+++ b/lava_dispatcher/actions/lmp/init_boards.py
@@ -75,6 +75,67 @@ def _validate_lmp_module(lmp_module_data):
Validator.validate(schema, lmp_module_data)
+def data_integrate(lmp_module_data, config):
+ # convert config date to lmp_module_data format
+ lmp_module_data_integrated = []
+ if config.lmp_hdmi_defconf is not None:
+ for module_name, module_defconf in config.lmp_hdmi_defconf.items():
+ module_init_item = {'hdmi': module_defconf, 'parameters': {'name': module_name}}
+ lmp_module_data_integrated.append(module_init_item)
+ if config.lmp_sata_defconf is not None:
+ for module_name, module_defconf in config.lmp_sata_defconf.items():
+ module_init_item = {'sata': module_defconf, 'parameters': {'name': module_name}}
+ lmp_module_data_integrated.append(module_init_item)
+ if config.lmp_eth_defconf is not None:
+ for module_name, module_defconf in config.lmp_eth_defconf.items():
+ module_init_item = {'eth': module_defconf, 'parameters': {'name': module_name}}
+ lmp_module_data_integrated.append(module_init_item)
+ if config.lmp_lsgpio_defconf is not None:
+ for module_name, module_defconf in config.lmp_lsgpio_defconf.items():
+ module_init_item = {'lsgpio': module_defconf, 'parameters': {'name': module_name}}
+ lmp_module_data_integrated.append(module_init_item)
+ if config.lmp_audio_defconf is not None:
+ for module_name, module_defconf in config.lmp_audio_defconf.items():
+ module_init_item = {'audio': module_defconf, 'parameters': {'name': module_name}}
+ lmp_module_data_integrated.append(module_init_item)
+ if config.lmp_usb_defconf is not None:
+ for module_name, module_defconf in config.lmp_usb_defconf.items():
+ module_init_item = {'usb': module_defconf, 'parameters': {'name': module_name}}
+ lmp_module_data_integrated.append(module_init_item)
+
+ logging.debug("lmp modules default init data is %s" % lmp_module_data_integrated.__str__())
+
+ # overlay lmp_module_data onto default config data
+ for lmp_module_element in lmp_module_data:
+ # get module_name first
+ if 'parameters' in lmp_module_element and\
+ 'name' in lmp_module_element['parameters']:
+ module_name = lmp_module_element['parameters']['name']
+ else:
+ module_name = config.lmp_default_name
+ # get module_type
+ for key_string in lmp_module_element.keys():
+ if key_string in ['hdmi', 'sata', 'eth', 'lsgpio', 'audio', 'usb']:
+ module_type = key_string
+ module_defconf = lmp_module_element[module_type]
+ logging.debug("lmp %s module %s init data is %s"
+ % (module_type, module_name, module_defconf))
+ # poll the default config data of LMP, overlay the default config by initial data in the job definition
+ for lmp_module_data_integrated_item in lmp_module_data_integrated:
+ if module_type in lmp_module_data_integrated_item:
+ logging.debug("__match lmp %s module type__" % module_type)
+ if lmp_module_data_integrated_item['parameters']['name'] == module_name:
+ logging.debug("init lmp %s module %s as %s(overlay %s)"
+ % (module_type, module_name, module_defconf,
+ lmp_module_data_integrated_item[module_type]))
+ lmp_module_data_integrated_item[module_type] = module_defconf
+
+ logging.debug("lmp modules final init data is %s" % lmp_module_data_integrated.__str__())
+
+ # return
+ return lmp_module_data_integrated
+
+
# init LMP module
def init(lmp_module_data, config):
_validate_lmp_module(lmp_module_data)
diff --git a/lava_dispatcher/config.py b/lava_dispatcher/config.py
index 9342a9b..76195d3 100644
--- a/lava_dispatcher/config.py
+++ b/lava_dispatcher/config.py
@@ -52,6 +52,8 @@ class DeviceSchema(schema.Schema):
boot_part_android_org = schema.IntOption()
boot_retries = schema.IntOption(default=3)
bootloader_prompt = schema.StringOption()
+ bootloader_timeout = schema.IntOption(default=120)
+ image_boot_msg_timeout = schema.IntOption(default=120)
send_char = schema.BoolOption(default=True)
test_image_prompts = schema.ListOption(default=["\(initramfs\)",
"linaro-test",
@@ -137,22 +139,28 @@ class DeviceSchema(schema.Schema):
# for the HDMI module of LMP
lmp_hdmi_id = schema.DictOption()
+ lmp_hdmi_defconf = schema.DictOption(default=None)
lmp_hdmi_version = schema.StringOption(default="unknown")
# for the SATA module of LMP
lmp_sata_id = schema.DictOption()
+ lmp_sata_defconf = schema.DictOption(default=None)
lmp_sata_version = schema.StringOption(default="unknown")
# for the ETH module of LMP
lmp_eth_id = schema.DictOption()
+ lmp_eth_defconf = schema.DictOption(default=None)
lmp_eth_version = schema.StringOption(default="unknown")
# for the LSGPIO module of LMP
lmp_lsgpio_id = schema.DictOption()
+ lmp_lsgpio_defconf = schema.DictOption(default=None)
+ lmp_audio_defconf = schema.DictOption(default=None)
lmp_lsgpio_version = schema.StringOption(default="unknown")
# for the USB module of LMP
lmp_usb_id = schema.DictOption()
+ lmp_usb_defconf = schema.DictOption(default=None)
lmp_usb_version = schema.StringOption(default="unknown")
# auto image login
@@ -181,28 +189,7 @@ class DeviceSchema(schema.Schema):
arm_probe_config = schema.StringOption(default='/usr/local/etc/arm-probe-config')
arm_probe_channels = schema.ListOption(default=['VDD_VCORE1'])
- uefi_image_filename = schema.StringOption(default=None)
customize = schema.DictOption(default=None)
- vexpress_uefi_path = schema.StringOption(default=None)
- vexpress_uefi_backup_path = schema.StringOption(default=None)
- vexpress_stop_autoboot_prompt = schema.StringOption(
- default='Press Enter to stop auto boot...')
- vexpress_usb_mass_storage_device = schema.StringOption(default=None)
-
- bl1_image_files = schema.ListOption(default=None)
- bl1_image_filename = schema.StringOption(default="bl1.bin")
- fip_image_files = schema.ListOption(default=None)
- fip_image_filename = schema.StringOption(default="fip.bin")
-
- wg_bl1_path = schema.StringOption(default="SOFTWARE/bl1.bin")
- wg_fip_path = schema.StringOption(default="SOFTWARE/fip.bin")
-
- wg_bl1_backup_path = schema.StringOption(default="SOFTWARE/backup-bl1.bin")
- wg_fip_backup_path = schema.StringOption(default="SOFTWARE/backup-fip.bin")
-
- wg_usb_mass_storage_device = schema.StringOption(default="/dev/disk/by-label/WG")
- wg_stop_autoboot_prompt = schema.StringOption(
- default='Press Enter to stop auto boot...')
ecmeip = schema.StringOption()
ipmi_power_sleep = schema.IntOption(default=1)
@@ -242,6 +229,8 @@ class DeviceSchema(schema.Schema):
simulator_bl31_files = schema.ListOption(default=None)
simulator_bl31 = schema.StringOption(default=None)
simulator_boot_wrapper = schema.StringOption(default=None)
+ simulator_uefi_default = schema.StringOption(default=None)
+ simulator_bl1_default = schema.StringOption(default=None)
# for dummy devices
dummy_driver = schema.StringOption(default=None)
@@ -279,11 +268,29 @@ class DeviceSchema(schema.Schema):
alternative_dir = schema.StringOption(default=None)
u_load_addrs = schema.ListOption(default=None)
z_load_addrs = schema.ListOption(default=None)
+ uimage_only = schema.BoolOption(default=False)
+ uimage_xip = schema.BoolOption(default=False)
+ append_dtb = schema.BoolOption(default=False)
# for dynamic_vm devices
dynamic_vm_backend_device_type = schema.StringOption(default='kvm')
dynamic_vm_host = schema.StringOption(default=None)
+ # for vexpress devices
+ vexpress_uefi_default = schema.StringOption(default=None)
+ vexpress_bl1_default = schema.StringOption(default=None)
+ vexpress_uefi_path = schema.StringOption(default=None)
+ vexpress_uefi_image_files = schema.ListOption(default=None)
+ vexpress_uefi_image_filename = schema.StringOption(default="fip.bin")
+ vexpress_uefi_backup_path = schema.StringOption(default=None)
+ vexpress_bl1_path = schema.StringOption(default=None)
+ vexpress_bl1_image_files = schema.ListOption(default=None)
+ vexpress_bl1_image_filename = schema.StringOption(default="bl1.bin")
+ vexpress_bl1_backup_path = schema.StringOption(default=None)
+ vexpress_stop_autoboot_prompt = schema.StringOption(default='Press Enter to stop auto boot...')
+ vexpress_usb_mass_storage_device = schema.StringOption(default=None)
+ vexpress_requires_trusted_firmware = schema.BoolOption(default=False)
+
class OptionDescriptor(object):
def __init__(self, name):
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/amarillo.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/amarillo.conf
index 61b0fa8..0c695f9 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/amarillo.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/amarillo.conf
@@ -14,7 +14,7 @@ boot_cmds_nfs =
setenv autoload no,
setenv fdt_high "'0xffffffff'",
setenv loadkernel "'tftp ${addr_kern} {KERNEL}'",
- setenv nfsargs "'setenv bootargs root=/dev/nfs rw nfsroot={SERVER_IP}:${NFSROOTFS} console=ttyAMA0 ip=dhcp'",
+ setenv nfsargs "'setenv bootargs root=/dev/nfs rw nfsroot={SERVER_IP}:${NFSROOTFS},tcp,hard,intr console=ttyAMA0 ip=dhcp'",
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run nfsargs; bootm 4000000'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/arndale-octa.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/arndale-octa.conf
index 1a0d777..c7fd2c3 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/arndale-octa.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/arndale-octa.conf
@@ -69,7 +69,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=tty0 console=ttySAC3,115200n8 mac=%(mac)s root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} ip=dhcp'",
+ setenv nfsargs "'setenv bootargs console=tty0 console=ttySAC3,115200n8 mac=%(mac)s root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp'",
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/arndale.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/arndale.conf
index 19093a7..a355a7c 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/arndale.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/arndale.conf
@@ -69,7 +69,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=ttySAC2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} earlyprintk ip=dhcp'",
+ setenv nfsargs "'setenv bootargs console=ttySAC2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr earlyprintk ip=dhcp'",
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/b2120stxh407.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/b2120stxh407.conf
index 36ca69e..3831b51 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/b2120stxh407.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/b2120stxh407.conf
@@ -15,4 +15,4 @@ connection_command = telnet %(jtag_stmc_ip)s 5331
boot_cmds_ramdisk = "console=ttyAS0,115200 CONSOLE=/dev/ttyAS0"
-boot_cmds_nfs = "'console=ttyAS0,115200 earlyprintk ip=dhcp root=/dev/nfs nfsroot={SERVER_IP}:{NFSROOTFS},tcp,nfsvers=3'"
+boot_cmds_nfs = "'console=ttyAS0,115200 earlyprintk ip=dhcp root=/dev/nfs nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr,nfsvers=3'"
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/beagle-xm.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/beagle-xm.conf
index 9629bf3..495732f 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/beagle-xm.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/beagle-xm.conf
@@ -2,7 +2,7 @@ client_type = bootloader
qemu_machine_type = beaglexm
lmc_dev_arg = beagle
-bootloader_prompt = OMAP3 beagleboard.org
+bootloader_prompt = U-Boot
mac = 00:40:5c:26:0a:6c
send_char = False
@@ -51,7 +51,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=ttyO2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} ip=dhcp'",
+ setenv nfsargs "'setenv bootargs console=ttyO2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp'",
setenv bootcmd "'usb start; dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone-black.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone-black.conf
index b8282d6..5836e1d 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone-black.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone-black.conf
@@ -38,7 +38,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=ttyO0,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} ip=dhcp'",
+ setenv nfsargs "'setenv bootargs console=ttyO0,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp'",
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone.conf
index b8282d6..5836e1d 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone.conf
@@ -38,7 +38,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=ttyO0,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} ip=dhcp'",
+ setenv nfsargs "'setenv bootargs console=ttyO0,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp'",
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/cubieboard3.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/cubieboard3.conf
index d24f2f6..666d2e8 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/cubieboard3.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/cubieboard3.conf
@@ -26,7 +26,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=ttyS0,115200 debug root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} ip=dhcp'",
+ setenv nfsargs "'setenv bootargs console=ttyS0,115200 debug root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp'",
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/d01.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/d01.conf
index 5b2bbde..9df7aa5 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/d01.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/d01.conf
@@ -110,7 +110,7 @@ boot_cmds_nfs = sendline b,
expect initrd2_tag.start,
sendline 3800040,
expect cmdline_tag.cmdline,
- sendline 'console=ttyS0,115200 root=/dev/nfs root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} ip=dhcp',
+ sendline 'console=ttyS0,115200 root=/dev/nfs root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp',
expect D01,
sendline setlinuxatag,
expect D01,
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/ifc6410.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/ifc6410.conf
index 3c05163..afd19db 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/ifc6410.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/ifc6410.conf
@@ -47,6 +47,7 @@ android_adb_over_usb = true
android_adb_over_tcp = false
fastboot_kernel_load_addr = 0x80200000
+append_dtb = True
boot_cmds_ramdisk = "loglevel=10 msm.hang_debug=n earlyprintk=serial,ttyHSL0,115200,n8 console=ttyHSL0,115200,n8 root=/dev/ram0 rootwait rw"
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/imx6q-wandboard.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/imx6q-wandboard.conf
index 30b24d1..dca7948 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/imx6q-wandboard.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/imx6q-wandboard.conf
@@ -24,7 +24,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=ttymxc0,115200 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} ip=dhcp'",
+ setenv nfsargs "'setenv bootargs console=ttymxc0,115200 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp'",
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/wg.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/juno.conf
index 2d745ed..00c50ec 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/wg.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/juno.conf
@@ -1,10 +1,46 @@
-client_type = wg
+client_type = vexpress
-bootloader_serial_delay_ms = 30
master_testboot_label = TESTBOOT
master_sdcard_label = SDCARD
+vexpress_uefi_path = SOFTWARE/fip.bin
+vexpress_uefi_backup_path = SOFTWARE/backup-fip.bin
+vexpress_uefi_image_filename = juno_fip.bin
+vexpress_uefi_image_files =
+ juno_fip.bin
+ fip.bin
+vexpress_bl1_path = SOFTWARE/bl1.bin
+vexpress_bl1_backup_path = SOFTWARE/backup-bl1.bin
+vexpress_bl1_image_filename = juno_bl1.bin
+vexpress_bl1_image_files =
+ juno_bl1.bin
+ bl1.bin
+vexpress_usb_mass_storage_device = /dev/disk/by-label/WG
+vexpress_requires_trusted_firmware = True
+vexpress_uefi_default = http://images.validation.linaro.org/juno/fip.bin
+vexpress_bl1_default = http://images.validation.linaro.org/juno/bl1.bin
-boot_cmds_master = sendline 3,
+interrupt_boot_prompt = The default boot selection will start in
+bootloader_prompt = Start:
+lmc_dev_arg = fastmodel
+android_orig_block_device = sda
+android_lava_block_device = sda
+partition_padding_string_android =
+partition_padding_string_org =
+sys_part_android = 5
+sdcard_part_android = 6
+data_part_android = 7
+read_boot_cmds_from_image = 0
+boot_retries = 5
+bootloader_serial_delay_ms = 30
+
+possible_partitions_files =
+ fstab.juno
+ init.partitions.rc
+ fstab.partitions
+ init.rc
+
+boot_cmds_master = expect Start:,
+ sendline 3,
expect Choice:,
sendline 3,
expect Delete entry:,
@@ -18,7 +54,7 @@ boot_cmds_master = sendline 3,
expect Choice:,
sendline 1,
expect Select the Boot Device:,
- sendline 2,
+ sendline 4,
expect File path of the EFI Application or the kernel:,
sendline Image,
expect Has FDT support? [y/n],
@@ -30,23 +66,24 @@ boot_cmds_master = sendline 3,
expect Description for this new Entry:,
sendline LAVA Master Image,
expect Choice:,
- sendline 4,
+ sendline 5,
expect Select the Boot Device:,
sendcontrol [,
sendcontrol M,
expect Choice:,
expect Choice:,
- sendline 4,
+ sendline 5,
expect Select the Boot Device:,
- sendline 2,
+ sendline 4,
expect File path of the FDT blob:,
sendline juno.dtb,
expect Choice:,
- sendline 5,
+ sendline 7,
expect Start:,
sendline 1
-boot_cmds = sendline 3,
+boot_cmds = expect Start:,
+ sendline 3,
expect Choice:,
sendline 3,
expect Delete entry:,
@@ -60,7 +97,7 @@ boot_cmds = sendline 3,
expect Choice:,
sendline 1,
expect Select the Boot Device:,
- sendline 3,
+ sendline 5,
expect File path of the EFI Application or the kernel:,
sendline Image,
expect Has FDT support? [y/n],
@@ -74,24 +111,25 @@ boot_cmds = sendline 3,
expect Description for this new Entry:,
sendline LAVA Ubuntu Test Image,
expect Choice:,
- sendline 4,
+ sendline 5,
expect Select the Boot Device:,
sendcontrol [,
sendcontrol M,
expect Choice:,
expect Choice:,
- sendline 4,
+ sendline 5,
expect Select the Boot Device:,
- sendline 3,
+ sendline 5,
expect File path of the FDT blob:,
sendline juno.dtb,
expect Choice:,
- sendline 5,
+ sendline 7,
expect Start:,
sendline 1
-boot_cmds_oe = sendline 3,
+boot_cmds_oe = expect Start:,
+ sendline 3,
expect Choice:,
sendline 3,
expect Delete entry:,
@@ -105,7 +143,7 @@ boot_cmds_oe = sendline 3,
expect Choice:,
sendline 1,
expect Select the Boot Device:,
- sendline 3,
+ sendline 5,
expect File path of the EFI Application or the kernel:,
sendline Image,
expect Has FDT support? [y/n],
@@ -117,24 +155,25 @@ boot_cmds_oe = sendline 3,
expect Description for this new Entry:,
sendline LAVA OE Test Image,
expect Choice:,
- sendline 4,
+ sendline 5,
expect Select the Boot Device:,
sendcontrol [,
sendcontrol M,
expect Choice:,
expect Choice:,
- sendline 4,
+ sendline 5,
expect Select the Boot Device:,
- sendline 3,
+ sendline 5,
expect File path of the FDT blob:,
sendline juno.dtb,
expect Choice:,
- sendline 5,
+ sendline 7,
expect Start:,
sendline 1
-boot_cmds_android = sendline 3,
+boot_cmds_android = expect Start:,
+ sendline 3,
expect Choice:,
sendline 3,
expect Delete entry:,
@@ -148,7 +187,7 @@ boot_cmds_android = sendline 3,
expect Choice:,
sendline 1,
expect Select the Boot Device:,
- sendline 3,
+ sendline 5,
expect File path of the EFI Application or the kernel:,
sendline kernel,
expect Has FDT support? [y/n],
@@ -162,62 +201,129 @@ boot_cmds_android = sendline 3,
expect Description for this new Entry:,
sendline LAVA Android Test Image,
expect Choice:,
- sendline 4,
+ sendline 5,
expect Select the Boot Device:,
sendcontrol [,
sendcontrol M,
expect Choice:,
expect Choice:,
- sendline 4,
+ sendline 5,
expect Select the Boot Device:,
- sendline 3,
+ sendline 5,
expect File path of the FDT blob:,
sendline juno.dtb,
expect Choice:,
- sendline 5,
+ sendline 7,
expect Start:,
sendline 1
-boot_retries = 5
-
-interrupt_boot_prompt = The default boot selection will start in
-
-bootloader_prompt = Start:
-
-lmc_dev_arg = fastmodel
-
-possible_partitions_files =
- fstab.juno
- init.partitions.rc
- fstab.partitions
- init.rc
-
-bl1_image_filename = juno_bl1.bin
-bl1_image_files =
- juno_bl1.bin
- bl1.bin
-fip_image_filename = juno_fip.bin
-fip_image_files =
- juno_fip.bin
- fip.bin
-
-wg_bl1_path = SOFTWARE/bl1.bin
-wg_fip_path = SOFTWARE/fip.bin
-
-wg_bl1_backup_path = SOFTWARE/backup-bl1.bin
-wg_fip_backup_path = SOFTWARE/backup-fip.bin
-
-wg_usb_mass_storage_device = /dev/disk/by-label/WG
-
-read_boot_cmds_from_image = 0
+boot_cmds_ramdisk = expect Start:,
+ sendline 3,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendcontrol [,
+ sendcontrol M,
+ expect Choice:,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 10,
+ expect Get the IP address from DHCP: [y/n],
+ sendline y,
+ expect Get the TFTP server IP address:,
+ sendline {SERVER_IP},
+ expect File path of the EFI Application or the kernel,
+ sendline {KERNEL},
+ expect Has FDT support? [y/n],
+ sendline y,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect Get the IP address from DHCP: [y/n],
+ sendline y,
+ expect Get the TFTP server IP address,
+ sendline {SERVER_IP},
+ expect File path of the initrd,
+ sendline {RAMDISK},
+ expect Arguments to pass to the binary:,
+ sendline "console=ttyAMA0,115200 earlyprintk=pl011,0x7ff80000 root=/dev/ram0 verbose debug ip=dhcp",
+ expect Description for this new Entry:,
+ sendline LAVA Ramdisk Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Select the Boot Device:,
+ sendcontrol [,
+ sendcontrol M,
+ expect Choice:,
+ expect Choice:,
+ sendline 5,
+ expect Select the Boot Device:,
+ sendline 10,
+ expect Get the IP address from DHCP: [y/n],
+ sendline y,
+ expect Get the TFTP server IP address:,
+ sendline {SERVER_IP},
+ expect File path of the FDT blob,
+ sendline {DTB},
+ expect Choice:,
+ sendline 7,
+ expect Start:,
+ sendline 1
-android_orig_block_device = sda
-android_lava_block_device = sda
-partition_padding_string_android =
-partition_padding_string_org =
-sys_part_android = 5
-sdcard_part_android = 6
-data_part_android = 7
+boot_cmds_nfs = expect Start:,
+ sendline 3,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendcontrol [,
+ sendcontrol M,
+ expect Choice:,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 10,
+ expect Get the IP address from DHCP: [y/n],
+ sendline y,
+ expect Get the TFTP server IP address:,
+ sendline {SERVER_IP},
+ expect File path of the EFI Application or the kernel,
+ sendline {KERNEL},
+ expect Has FDT support? [y/n],
+ sendline y,
+ expect Add an initrd: [y/n],
+ sendline n,
+ expect Arguments to pass to the binary:,
+ sendline "console=ttyAMA0,115200 earlyprintk=pl011,0x7ff80000 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp",
+ expect Description for this new Entry:,
+ sendline LAVA NFS Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Select the Boot Device:,
+ sendcontrol [,
+ sendcontrol M,
+ expect Choice:,
+ expect Choice:,
+ sendline 5,
+ expect Select the Boot Device:,
+ sendline 10,
+ expect Get the IP address from DHCP: [y/n],
+ sendline y,
+ expect Get the TFTP server IP address:,
+ sendline {SERVER_IP},
+ expect File path of the FDT blob,
+ sendline {DTB},
+ expect Choice:,
+ sendline 7,
+ expect Start:,
+ sendline 1
boot_options =
boot_cmds
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/keystone.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/keystone.conf
index 4c825fb..92672f8 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/keystone.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/keystone.conf
@@ -22,6 +22,21 @@ boot_cmds_ramdisk =
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run loadbootmon; run run_mon; run run_kern'",
boot
+boot_cmds_nfs =
+ setenv eth1addr %(eth1addr)s,
+ setenv fdt_high "'0xffffffff'",
+ setenv addr_kern "'0x88000000'",
+ setenv addr_fdt "'0x87000000'",
+ setenv addr_mon "'0xc5f0000'",
+ setenv autoload no,
+ setenv loadkernel "'tftp ${addr_kern} {KERNEL}'",
+ setenv loadfdt "'tftp ${addr_fdt} {DTB}'",
+ setenv loadbootmon "'tftp ${addr_mon} {FIRMWARE}'",
+ setenv nfsargs "'setenv bootargs root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr console=ttyS0,115200n8 ip=dhcp'",
+ setenv usb_ethernet "'usb start; setenv ethact asx0'",
+ setenv bootcmd "'run usb_ethernet; dhcp; setenv serverip {SERVER_IP}; run loadkernel; run nfsargs; run loadfdt; run loadbootmon; run run_mon; run run_kern'",
+ boot
+
boot_options =
boot_cmds
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/mcdivitt.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/mcdivitt.conf
new file mode 100644
index 0000000..c9ffc2b
--- /dev/null
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/mcdivitt.conf
@@ -0,0 +1,42 @@
+client_type = bootloader
+
+bootloader_prompt = HP ProLiant m400
+
+u_load_addrs =
+ 0x4002000000
+ 0x4005000000
+ 0x4003000000
+
+z_load_addrs =
+ 0x4002000000
+ 0x4005000000
+ 0x4003000000
+
+boot_cmds_nfs =
+ setenv autoload no,
+ setenv kernel_addr_r "'{KERNEL_ADDR}'",
+ setenv initrd_addr_r "'{RAMDISK_ADDR}'",
+ setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
+ setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}'",
+ setenv nfsargs "'setenv bootargs root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr console=ttyS0,115200 earlyprintk=uart8250-32bit,0x1c021000 debug maxcpus=8 swiotlb=65536 ip=dhcp'",
+ setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run nfsargs; bootm ${kernel_addr_r} ${initrd_addr_r} ${fdt_addr_r}'",
+ boot
+
+boot_cmds_ramdisk =
+ setenv autoload no,
+ setenv kernel_addr_r "'{KERNEL_ADDR}'",
+ setenv initrd_addr_r "'{RAMDISK_ADDR}'",
+ setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
+ setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}'",
+ setenv bootargs "'root=/dev/ram0 rw console=ttyS0,115200 earlyprintk=uart8250-32bit,0x1c021000 debug maxcpus=8 swiotlb=65536 ip=dhcp'",
+ setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; bootm ${kernel_addr_r} ${initrd_addr_r} ${fdt_addr_r}'",
+ boot
+
+boot_cmds =
+ boot
+
+boot_options =
+ boot_cmds
+
+[boot_cmds]
+default = boot_cmds \ No newline at end of file
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/mustang.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/mustang.conf
index 9f17754..abd753b 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/mustang.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/mustang.conf
@@ -2,6 +2,7 @@ client_type = bootloader
bootloader_prompt = Mustang
send_char = False
+uimage_only = True
u_load_addrs =
0x4002000000
@@ -21,7 +22,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} panic=1 console=ttyS0,115200 earlyprintk=uart8250-32bit,0x1c020000 debug ip=dhcp'",
+ setenv nfsargs "'setenv bootargs root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr panic=1 console=ttyS0,115200 earlyprintk=uart8250-32bit,0x1c020000 debug ip=dhcp'",
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/panda-es.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/panda-es.conf
index 4c8668c..4b4ebc9 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/panda-es.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/panda-es.conf
@@ -30,6 +30,7 @@ boot_cmds = mmc init,
root=LABEL=testrootfs rootwait ro earlyprintk fixrtc nocompcache
vram=48M omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000'",
boot
+
boot_cmds_android = mmc init,
mmc part 0,
setenv bootcmd "'fatload mmc 0:3 0x80200000 uImage;
@@ -67,7 +68,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=ttyO2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} ip=dhcp fixrtc nocompcache vram=48M omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000 init=init'",
+ setenv nfsargs "'setenv bootargs console=ttyO2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp fixrtc nocompcache vram=48M omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000 init=init'",
setenv bootcmd "'usb start; dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/panda.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/panda.conf
index 4c8668c..4b4ebc9 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/panda.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/panda.conf
@@ -30,6 +30,7 @@ boot_cmds = mmc init,
root=LABEL=testrootfs rootwait ro earlyprintk fixrtc nocompcache
vram=48M omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000'",
boot
+
boot_cmds_android = mmc init,
mmc part 0,
setenv bootcmd "'fatload mmc 0:3 0x80200000 uImage;
@@ -67,7 +68,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=ttyO2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} ip=dhcp fixrtc nocompcache vram=48M omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000 init=init'",
+ setenv nfsargs "'setenv bootargs console=ttyO2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp fixrtc nocompcache vram=48M omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000 init=init'",
setenv bootcmd "'usb start; dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base-aemv8a.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base-aemv8a.conf
index d1a138e..80c924e 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base-aemv8a.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base-aemv8a.conf
@@ -95,6 +95,9 @@ simulator_uefi_files =
fvp_fip.bin
uefi_fvp-base.bin
+simulator_uefi_default = http://images.validation.linaro.org/fvp/fvp_fip.bin
+simulator_bl1_default = http://images.validation.linaro.org/fvp/fvp_bl1.bin
+
license_file = 8224@localhost
sim_bin = /opt/arm/FVP_Base_AEMv8A-AEMv8A/models/Linux64_GCC-4.1/FVP_Base_AEMv8A-AEMv8A
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x1-a53x1.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x1-a53x1.conf
index 2d691a0..c939cee 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x1-a53x1.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x1-a53x1.conf
@@ -95,6 +95,9 @@ simulator_uefi_files =
fvp_fip.bin
uefi_fvp-base.bin
+simulator_uefi_default = http://images.validation.linaro.org/fvp/fvp_fip.bin
+simulator_bl1_default = http://images.validation.linaro.org/fvp/fvp_bl1.bin
+
license_file = 8224@localhost
sim_bin = /opt/arm/FVP_Base_Cortex-A57-A53x14/models/Linux64_GCC-4.1/FVP_Base_Cortex-A57x1-A53x1
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x4-a53x4.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x4-a53x4.conf
index fbd8219..5d1a94f 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x4-a53x4.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_fvp_base_cortex-a57x4-a53x4.conf
@@ -95,6 +95,9 @@ simulator_uefi_files =
fvp_fip.bin
uefi_fvp-base.bin
+simulator_uefi_default = http://images.validation.linaro.org/fvp/fvp_fip.bin
+simulator_bl1_default = http://images.validation.linaro.org/fvp/fvp_bl1.bin
+
license_file = 8224@localhost
sim_bin = /opt/arm/FVP_Base_Cortex-A57-A53x14/models/Linux64_GCC-4.1/FVP_Base_Cortex-A57x4-A53x4
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x1-a7x1.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x1-a7x1.conf
index 7b3ce78..c525c67 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x1-a7x1.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x1-a7x1.conf
@@ -81,16 +81,16 @@ simulator_boot_wrapper = -a coretile.cluster0.*={AXF}
simulator_command = sudo -u lavaserver ARMLMD_LICENSE_FILE="%(license_file)s" %(sim_bin)s
boot_options =
- motherboard.mmc.p_mmc_file
- motherboard.hostbridge.userNetPorts
- motherboard.smsc_91c111.enabled
- motherboard.hostbridge.userNetworking
- motherboard.flashloader0.fname
- motherboard.flashloader1.fname
- motherboard.flashloader1.fnameWrite
- coretile.cache_state_modelled
- coretile.cluster0.cpu0.semihosting-enable
- coretile.cluster0.cpu0.semihosting-cmd_line
+ motherboard.mmc.p_mmc_file
+ motherboard.hostbridge.userNetPorts
+ motherboard.smsc_91c111.enabled
+ motherboard.hostbridge.userNetworking
+ motherboard.flashloader0.fname
+ motherboard.flashloader1.fname
+ motherboard.flashloader1.fnameWrite
+ coretile.cache_state_modelled
+ coretile.cluster0.cpu0.semihosting-enable
+ coretile.cluster0.cpu0.semihosting-cmd_line
[motherboard.mmc.p_mmc_file]
default = {IMG}
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x4-a7x4.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x4-a7x4.conf
index a3ec9ab..29e00cb 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x4-a7x4.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-a15x4-a7x4.conf
@@ -81,16 +81,16 @@ simulator_boot_wrapper = -a coretile.cluster0.*={AXF}
simulator_command = sudo -u lavaserver ARMLMD_LICENSE_FILE="%(license_file)s" %(sim_bin)s
boot_options =
- motherboard.mmc.p_mmc_file
- motherboard.hostbridge.userNetPorts
- motherboard.smsc_91c111.enabled
- motherboard.hostbridge.userNetworking
- motherboard.flashloader0.fname
- motherboard.flashloader1.fname
- motherboard.flashloader1.fnameWrite
- coretile.cache_state_modelled
- coretile.cluster0.cpu0.semihosting-enable
- coretile.cluster0.cpu0.semihosting-cmd_line
+ motherboard.mmc.p_mmc_file
+ motherboard.hostbridge.userNetPorts
+ motherboard.smsc_91c111.enabled
+ motherboard.hostbridge.userNetworking
+ motherboard.flashloader0.fname
+ motherboard.flashloader1.fname
+ motherboard.flashloader1.fnameWrite
+ coretile.cache_state_modelled
+ coretile.cluster0.cpu0.semihosting-enable
+ coretile.cluster0.cpu0.semihosting-cmd_line
[motherboard.mmc.p_mmc_file]
default = {IMG}
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-armv8.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-armv8.conf
index ea506e5..cd160b4 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-armv8.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/rtsm_ve-armv8.conf
@@ -61,7 +61,7 @@ simulator_boot_wrapper = -a {AXF}
simulator_command = sudo -u lavaserver ARMLMD_LICENSE_FILE="%(license_file)s" %(sim_bin)s %(sim_model)s
boot_options =
- motherboard.mmc.p_mmc_file
+ motherboard.mmc.p_mmc_file
motherboard.smsc_91c111.enabled
cluster.NUM_CORES
cluster.cpu0.unpredictable_WPMASKANDBAS
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/snowball.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/snowball.conf
index 7cd0a67..65863c7 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/snowball.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/snowball.conf
@@ -7,6 +7,9 @@ android_orig_block_device = mmcblk1
android_lava_block_device = mmcblk1
mac = 3e:c4:73:05:d1:a1
send_char = False
+uimage_only = True
+uimage_xip = True
+append_dtb = True
soft_boot_cmd = echo "Restarting system."
echo 0x02 > /sys/kernel/debug/ab8500/register-bank
@@ -16,13 +19,13 @@ soft_boot_cmd = echo "Restarting system."
echo 0x11 > /sys/kernel/debug/ab8500/register-value
u_load_addrs =
- 0x00100000
0x01000000
+ 0x03000000
0x00f00000
z_load_addrs =
- 0x00100000
0x01000000
+ 0x03000000
0x00f00000
boot_cmds =
@@ -57,7 +60,7 @@ boot_cmds_nfs =
setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
setenv loadfdt "'tftp ${fdt_addr_r} {DTB}'",
- setenv nfsargs "'setenv bootargs console=tty0 console=ttyAMA2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS} fixrtc nocompcache vmalloc=300M mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M mem=22M@360M mem_issw=1M@383M mem=640M@384M ip=dhcp'",
+ setenv nfsargs "'setenv bootargs console=tty0 console=ttyAMA2,115200n8 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr fixrtc nocompcache vmalloc=300M mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M mem=22M@360M mem_issw=1M@383M mem=640M@384M ip=dhcp'",
setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run loadfdt; run nfsargs; {BOOTX}'",
boot
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/stx7108.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/stx7108.conf
index c352280..fe7eb6f 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/stx7108.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/stx7108.conf
@@ -13,4 +13,4 @@ connection_command = telnet %(jtag_stmc_ip)s 5331
stx7108_mac = 00:00:00:00:00:00
-boot_cmds_nfs = "'console=ttyAS1,115200 root=/dev/nfs nfsroot={SERVER_IP}:{NFSROOTFS},nfsvers=3,rsize=4096,wsize=8192,tcp nwhwconf=device:eth0,hwaddr:%(stx7108_mac)s ip=dhcp bpa2parts=bigphysarea:64M::,modules:2M::'"
+boot_cmds_nfs = "'console=ttyAS1,115200 root=/dev/nfs nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr,nfsvers=3,rsize=4096,wsize=8192 nwhwconf=device:eth0,hwaddr:%(stx7108_mac)s ip=dhcp bpa2parts=bigphysarea:64M::,modules:2M::'"
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/utilite-pro.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/utilite-pro.conf
new file mode 100644
index 0000000..fc4be1a
--- /dev/null
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/utilite-pro.conf
@@ -0,0 +1,37 @@
+client_type = bootloader
+
+u_load_addrs =
+ 0x10800000
+ 0x11800000
+ 0x12000000
+
+z_load_addrs =
+ 0x11000000
+ 0x13000000
+ 0x12000000
+
+boot_cmds_ramdisk =
+ setenv autoload no,
+ setenv kernel_addr_r "'{KERNEL_ADDR}'",
+ setenv initrd_addr_r "'{RAMDISK_ADDR}'",
+ setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
+ setenv loadinitrd "'tftp ${initrd_addr_r} {RAMDISK}; setenv initrd_size ${filesize}'",
+ setenv bootargs "'console=ttymxc3,115200 root=/dev/ram0 ip=dhcp'",
+ setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; {BOOTX}'",
+ boot
+
+boot_cmds_nfs =
+ setenv autoload no,
+ setenv kernel_addr_r "'{KERNEL_ADDR}'",
+ setenv loadkernel "'tftp ${kernel_addr_r} {KERNEL}'",
+ setenv nfsargs "'setenv bootargs console=ttymxc3,115200 root=/dev/nfs rw nfsroot={SERVER_IP}:{NFSROOTFS},tcp,hard,intr ip=dhcp'",
+ setenv bootcmd "'dhcp; setenv serverip {SERVER_IP}; run loadkernel; run loadinitrd; run nfsargs; {BOOTX}'",
+ boot
+
+bootloader_prompt = CM-FX6
+
+boot_options =
+ boot_cmds
+
+[boot_cmds]
+default = boot_cmds \ No newline at end of file
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-a5.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-a5.conf
new file mode 100644
index 0000000..09bc2d1
--- /dev/null
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-a5.conf
@@ -0,0 +1,151 @@
+# DO NOT EDIT: MANAGED BY SALT!
+
+bootloader_serial_delay_ms = 30
+
+boot_cmds_master = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 1,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=ttyAMA0,38400n8 root=/dev/mmcblk0p2 rootwait ro mem=1024M",
+ expect File path of the local FDT:,
+ sendline v2p-ca5s.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Master Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_cmds = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 2,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=tty0 console=ttyAMA0,38400n8 root=/dev/mmcblk0p5 rootwait ro androidboot.console=ttyAMA0",
+ expect File path of the local FDT:,
+ sendline v2p-ca5s.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_cmds_oe = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 2,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=tty0 console=ttyAMA0,38400n8 root=/dev/mmcblk0p5 rootwait ro androidboot.console=ttyAMA0",
+ expect File path of the local FDT:,
+ sendline v2p-ca5s.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_cmds_android = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 2,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=tty0 console=ttyAMA0,38400n8 root=/dev/mmcblk0p5 rootwait ro androidboot.console=ttyAMA0",
+ expect File path of the local FDT:,
+ sendline v2p-ca5s.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Android Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_retries = 5
+
+interrupt_boot_prompt = The default boot selection will start in
+
+bootloader_prompt = Start:
+
+client_type = vexpress
+
+lmc_dev_arg = vexpress
+
+possible_partitions_files =
+ init.partitions.rc
+ fstab.partitions
+ init.rc
+ fstab.arm-versatileexpress
+
+vexpress_uefi_image_filename = uefi_v2p-ca5s.bin
+
+vexpress_uefi_image_files =
+ uefi_v2p-ca5s.bin
+
+vexpress_uefi_path = SOFTWARE/A5/uefi.bin
+
+vexpress_uefi_backup_path = SOFTWARE/A5/backup-uefi.bin
+
+vexpress_usb_mass_storage_device = /dev/disk/by-label/VEMSD
+
+read_boot_cmds_from_image = 0
+
+boot_options =
+ boot_cmds
+
+[boot_cmds]
+default = boot_cmds
+
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-a9.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-a9.conf
new file mode 100644
index 0000000..acdd784
--- /dev/null
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-a9.conf
@@ -0,0 +1,151 @@
+# DO NOT EDIT: MANAGED BY SALT!
+
+bootloader_serial_delay_ms = 30
+
+boot_cmds_master = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 1,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=ttyAMA0,38400n8 root=/dev/mmcblk0p2 rootwait ro mem=1024M",
+ expect File path of the local FDT:,
+ sendline v2p-ca9.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Master Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_cmds = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 2,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=tty0 console=ttyAMA0,38400n8 root=/dev/mmcblk0p5 rootwait ro androidboot.console=ttyAMA0",
+ expect File path of the local FDT:,
+ sendline v2p-ca9.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_cmds_oe = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 2,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=tty0 console=ttyAMA0,38400n8 root=/dev/mmcblk0p5 rootwait ro androidboot.console=ttyAMA0",
+ expect File path of the local FDT:,
+ sendline v2p-ca9.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_cmds_android = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 2,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=tty0 console=ttyAMA0,38400n8 root=/dev/mmcblk0p5 rootwait ro androidboot.console=ttyAMA0",
+ expect File path of the local FDT:,
+ sendline v2p-ca9.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Android Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_retries = 5
+
+interrupt_boot_prompt = The default boot selection will start in
+
+bootloader_prompt = Start:
+
+client_type = vexpress
+
+lmc_dev_arg = vexpress
+
+possible_partitions_files =
+ init.partitions.rc
+ fstab.partitions
+ init.rc
+ fstab.arm-versatileexpress
+
+vexpress_uefi_image_filename = uefi_v2p-ca9.bin
+
+vexpress_uefi_image_files =
+ uefi_v2p-ca9.bin
+
+vexpress_uefi_path = SOFTWARE/A9/uefi.bin
+
+vexpress_uefi_backup_path = SOFTWARE/A9/backup-uefi.bin
+
+vexpress_usb_mass_storage_device = /dev/disk/by-label/VEMSD
+
+read_boot_cmds_from_image = 0
+
+boot_options =
+ boot_cmds
+
+[boot_cmds]
+default = boot_cmds
+
diff --git a/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-tc2.conf b/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-tc2.conf
index 6337298..2dff7be 100644
--- a/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-tc2.conf
+++ b/lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-tc2.conf
@@ -1,13 +1,144 @@
client_type = vexpress
+bootloader_serial_delay_ms = 30
+
+boot_cmds_master = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 1,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=ttyAMA0,38400n8 root=/dev/mmcblk0p2 rootwait ro mem=1024M",
+ expect File path of the local FDT:,
+ sendline v2p-ca15-tc2.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Master Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_cmds = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 2,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=tty0 console=ttyAMA0,38400n8 root=/dev/sda1 rootwait ro androidboot.console=ttyAMA0",
+ expect File path of the local FDT:,
+ sendline v2p-ca15-tc2.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_cmds_oe = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 2,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=tty0 console=ttyAMA0,38400n8 root=/dev/sda1 rootwait ro androidboot.console=ttyAMA0",
+ expect File path of the local FDT:,
+ sendline v2p-ca15-tc2.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_cmds_android = sendline a,
+ expect Choice:,
+ sendline 3,
+ expect Delete entry:,
+ sendline 1,
+ expect Choice:,
+ sendline 1,
+ expect Select the Boot Device:,
+ sendline 2,
+ expect File path of the EFI Application or the kernel:,
+ sendline uImage,
+ expect "Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l]",
+ sendline l,
+ expect Add an initrd: [y/n],
+ sendline y,
+ expect File path of the initrd,
+ sendline uInitrd,
+ expect Arguments to pass to the binary:,
+ sendline "console=tty0 console=ttyAMA0,38400n8 root=/dev/sda1 rootwait ro androidboot.console=ttyAMA0",
+ expect File path of the local FDT:,
+ sendline v2p-ca15-tc2.dtb,
+ expect Description for this new Entry:,
+ sendline LAVA Android Test Image,
+ expect Choice:,
+ sendline 5,
+ expect Start:,
+ sendline 1
+
+boot_retries = 5
+
interrupt_boot_prompt = The default boot selection will start in
+
bootloader_prompt = Start:
+
lmc_dev_arg = vexpress
-uefi_image_filename = uefi_v2p-ca15-tc2.bin
+possible_partitions_files =
+ init.partitions.rc
+ fstab.partitions
+ init.rc
+ fstab.arm-versatileexpress
+
+vexpress_uefi_image_filename = uefi_v2p-ca15-tc2.bin
+
+vexpress_uefi_image_files =
+ uefi_v2p-ca15-tc2.bin
+
vexpress_uefi_path = SOFTWARE/TC2/uefi.bin
+
vexpress_uefi_backup_path = SOFTWARE/TC2/backup-uefi.bin
+
vexpress_usb_mass_storage_device = /dev/disk/by-label/VEMSD
+
read_boot_cmds_from_image = 0
android_orig_block_device = mmcblk0
@@ -17,18 +148,8 @@ sys_part_android = 1
sdcard_part_android = 3
data_part_android = 2
-possible_partitions_files =
- init.partitions.rc
- fstab.partitions
- init.rc
- fstab.arm-versatileexpress
-
-boot_cmds = 2
-
-boot_cmds_android = 3
-
boot_options =
boot_cmds
[boot_cmds]
-default = boot_cmds
+default = boot_cmds \ No newline at end of file
diff --git a/lava_dispatcher/device/bootloader.py b/lava_dispatcher/device/bootloader.py
index 5ee2144..b1b21a4 100644
--- a/lava_dispatcher/device/bootloader.py
+++ b/lava_dispatcher/device/bootloader.py
@@ -33,6 +33,9 @@ from lava_dispatcher.utils import (
extract_ramdisk,
create_ramdisk,
ensure_directory,
+ append_dtb,
+ create_uimage,
+ is_uimage,
)
from lava_dispatcher.errors import (
CriticalError,
@@ -78,13 +81,8 @@ class BootloaderTarget(MasterImageTarget):
def _get_uboot_boot_command(self, kernel, ramdisk, dtb):
bootz = False
bootx = []
- uimage = ['u-boot', 'uImage']
- # Detect if zImage or uImage is used.
- # Raw ELF images are not supported by u-boot.
- cmd = 'file ' + kernel
- output = self.context.run_command_get_output(cmd)
- if any(x in output for x in uimage):
+ if is_uimage(kernel, self.context):
logging.info('Attempting to set boot command as bootm')
bootx.append('bootm')
else:
@@ -166,6 +164,14 @@ class BootloaderTarget(MasterImageTarget):
# We have been passed kernel image
kernel = download_image(kernel, self.context,
self._tmpdir, decompress=False)
+ if self.config.uimage_only and not is_uimage(kernel, self.context):
+ if len(self.config.u_load_addrs) == 3:
+ kernel = create_uimage(kernel, self.config.u_load_addrs[0],
+ self._tmpdir, self.config.uimage_xip)
+ logging.info('uImage created successfully')
+ else:
+ logging.error('Undefined u_load_addrs, aborting uImage creation')
+
self._boot_tags['{KERNEL}'] = self._get_rel_path(kernel, self._base_tmpdir)
if ramdisk is not None:
# We have been passed a ramdisk
@@ -197,7 +203,12 @@ class BootloaderTarget(MasterImageTarget):
# We have been passed a device tree blob
dtb = download_image(dtb, self.context,
self._tmpdir, decompress=False)
- self._boot_tags['{DTB}'] = self._get_rel_path(dtb, self._base_tmpdir)
+ if self.config.append_dtb:
+ kernel = append_dtb(kernel, dtb, self._tmpdir)
+ logging.info('Appended dtb to kernel image successfully')
+ self._boot_tags['{KERNEL}'] = self._get_rel_path(kernel, self._base_tmpdir)
+ else:
+ self._boot_tags['{DTB}'] = self._get_rel_path(dtb, self._base_tmpdir)
if rootfs is not None:
# We have been passed a rootfs
rootfs = download_image(rootfs, self.context,
@@ -293,6 +304,7 @@ class BootloaderTarget(MasterImageTarget):
bootloadertype)
def _run_boot(self):
+ self._load_test_firmware()
self._enter_bootloader(self.proc)
boot_cmds = self._load_boot_cmds(default=self._default_boot_cmds,
boot_tags=self._boot_tags)
@@ -301,7 +313,8 @@ class BootloaderTarget(MasterImageTarget):
self.proc.sendline(self.config.pre_boot_cmd,
send_char=self.config.send_char)
self._customize_bootloader(self.proc, boot_cmds)
- self.proc.expect(self.config.image_boot_msg, timeout=300)
+ self.proc.expect(self.config.image_boot_msg,
+ timeout=self.config.image_boot_msg_timeout)
self._auto_login(self.proc)
self._wait_for_prompt(self.proc, self.config.test_image_prompts,
self.config.boot_linaro_timeout)
diff --git a/lava_dispatcher/device/fastboot.py b/lava_dispatcher/device/fastboot.py
index ce12793..399ba62 100644
--- a/lava_dispatcher/device/fastboot.py
+++ b/lava_dispatcher/device/fastboot.py
@@ -85,6 +85,11 @@ class FastbootTarget(Target):
attempts += 1
continue
+ if not deployed:
+ msg = "Deployment Failed"
+ logging.critical(msg)
+ raise CriticalError(msg)
+
def deploy_android(self, boot, system, userdata, rootfstype,
bootloadertype, target_type):
self._target_type = target_type
@@ -107,6 +112,11 @@ class FastbootTarget(Target):
attempts += 1
continue
+ if not deployed:
+ msg = "Deployment Failed"
+ logging.critical(msg)
+ raise CriticalError(msg)
+
def get_device_version(self):
# this is tricky, because fastboot does not have a visible version
# number. For now let's use just the adb version number.
diff --git a/lava_dispatcher/device/fastboot_drivers.py b/lava_dispatcher/device/fastboot_drivers.py
index 8b152dd..26cfc20 100644
--- a/lava_dispatcher/device/fastboot_drivers.py
+++ b/lava_dispatcher/device/fastboot_drivers.py
@@ -35,6 +35,7 @@ from lava_dispatcher.utils import (
extract_ramdisk,
extract_modules,
create_ramdisk,
+ append_dtb,
)
@@ -177,6 +178,11 @@ class BaseDriver(object):
is_uboot=False)
extract_modules(modules, ramdisk_dir)
self._ramdisk = create_ramdisk(ramdisk_dir, self._working_dir)
+ if dtb is not None:
+ dtb = self._get_image(dtb)
+ if self.config.append_dtb:
+ self._kernel = append_dtb(self._kernel, dtb, self.working_dir)
+ logging.info('Appended dtb to kernel image successfully')
if rootfs is not None:
self._default_boot_cmds = 'boot_cmds_rootfs'
rootfs = self._get_image(rootfs)
diff --git a/lava_dispatcher/device/fastmodel.py b/lava_dispatcher/device/fastmodel.py
index 191f064..fdbce90 100644
--- a/lava_dispatcher/device/fastmodel.py
+++ b/lava_dispatcher/device/fastmodel.py
@@ -275,10 +275,6 @@ class FastModelTarget(Target):
raise CriticalError("A ramdisk image is required")
elif dtb is None:
raise CriticalError("A dtb is required")
- elif bootloader is None:
- raise CriticalError("UEFI image is required")
- elif bootloader is None:
- raise CriticalError("BL1 firmware is required")
if rootfs is not None or nfsrootfs is not None or firmware is not None:
logging.warn("This platform only suports ramdisk booting, ignoring other parameters")
@@ -302,12 +298,28 @@ class FastModelTarget(Target):
self._dtb = download_image(dtb, self.context, self._scratch_dir,
decompress=False)
self._boot_tags['{DTB}'] = os.path.relpath(self._dtb, self._scratch_dir)
- self._uefi = download_image(bootloader, self.context, self._scratch_dir,
- decompress=False)
- self._bl1 = download_image(bl1, self.context, self._scratch_dir,
- decompress=False)
# Optional
+ if bootloader is None:
+ if self.config.simulator_uefi_default is None:
+ raise CriticalError("UEFI image is required")
+ else:
+ self._uefi = download_image(self.config.simulator_uefi_default, self.context,
+ self._scratch_dir, decompress=False)
+ else:
+ self._uefi = download_image(bootloader, self.context,
+ self._scratch_dir, decompress=False)
+
+ if bl1 is None:
+ if self.config.simulator_bl1_default is None:
+ raise CriticalError("BL1 firmware is required")
+ else:
+ self._bl1 = download_image(self.config.simulator_bl1_default, self.context,
+ self._scratch_dir, decompress=False)
+ else:
+ self._bl1 = download_image(bl1, self.context,
+ self._scratch_dir, decompress=False)
+
if bl2 is not None:
self._bl2 = download_image(bl2, self.context, self._scratch_dir,
decompress=False)
@@ -315,6 +327,11 @@ class FastModelTarget(Target):
self._bl31 = download_image(bl31, self.context, self._scratch_dir,
decompress=False)
+ if self.config.simulator_uefi_vars and self._uefi_vars is None:
+ # Create file for flashloader1
+ self._uefi_vars = os.path.join(self._scratch_dir, self.config.simulator_uefi_vars)
+ touch(self._uefi_vars)
+
# Get deployment data
self.deployment_data = deployment_data.get(target_type)
@@ -371,12 +388,10 @@ class FastModelTarget(Target):
os.chmod(os.path.join(root, f), 0o777)
def power_off(self, proc):
- try:
+ if self._uefi_vars is not None:
logging.info('Requesting graceful shutdown')
self._sim_proc.kill(signal.SIGTERM)
- self._sim_proc.expect('FlashLoader: Saved', timeout=10)
- except pexpect.TIMEOUT:
- logging.info('Unable to gracefully shutdown')
+ self._sim_proc.wait()
super(FastModelTarget, self).power_off(proc)
finalize_process(self._sim_proc)
self._sim_proc = None
diff --git a/lava_dispatcher/device/ipmi_tftp.py b/lava_dispatcher/device/ipmi_tftp.py
index c62910e..8e7db13 100644
--- a/lava_dispatcher/device/ipmi_tftp.py
+++ b/lava_dispatcher/device/ipmi_tftp.py
@@ -183,7 +183,8 @@ class IpmiPxeTarget(Target):
self._enter_bootloader(self.proc)
boot_cmds = self._load_boot_cmds(default='boot_cmds_master')
self._customize_bootloader(self.proc, boot_cmds)
- self.proc.expect(self.config.image_boot_msg, timeout=300)
+ self.proc.expect(self.config.image_boot_msg,
+ timeout=self.config.image_boot_msg_timeout)
self._wait_for_prompt(self.proc, self.config.test_image_prompts,
self.config.boot_linaro_timeout)
self.proc.sendline('export PS1="%s"' % self.MASTER_PS1)
diff --git a/lava_dispatcher/device/jtag_drivers.py b/lava_dispatcher/device/jtag_drivers.py
index 3c7b4c4..cf3a11f 100644
--- a/lava_dispatcher/device/jtag_drivers.py
+++ b/lava_dispatcher/device/jtag_drivers.py
@@ -175,7 +175,8 @@ class stmc(BaseDriver):
# Ask the master to deliver the image
self.context.transport.request_send('lava_ms_boot', None)
- proc.expect(self.config.image_boot_msg, timeout=300)
+ proc.expect(self.config.image_boot_msg,
+ timeout=self.config.image_boot_msg_timeout)
return proc
else:
boot_cmds.insert(0, self._stmc_command)
@@ -225,5 +226,6 @@ class stmc(BaseDriver):
logging.info("Delivering images with STMC")
self.context.run_command(jtag_command, failok=False)
- proc.expect(self.config.image_boot_msg, timeout=300)
+ proc.expect(self.config.image_boot_msg,
+ timeout=self.config.image_boot_msg_timeout)
return proc
diff --git a/lava_dispatcher/device/master.py b/lava_dispatcher/device/master.py
index 83968d8..41cef4a 100644
--- a/lava_dispatcher/device/master.py
+++ b/lava_dispatcher/device/master.py
@@ -274,11 +274,16 @@ class MasterImageTarget(Target):
logging.debug("Unable to read boot commands dynamically.")
def _format_testpartition(self, runner, fstype):
+ force = ""
logging.info("Format testboot and testrootfs partitions")
+ if fstype.startswith("ext"):
+ force = "-F"
+ elif fstype == "btrfs":
+ force = "-f"
runner.run('umount %s' % self.testrootfs_path, failok=True)
- runner.run('nice mkfs -t %s -q %s -L %s'
- % (fstype, self.testrootfs_path, self.testrootfs_label), timeout=1800)
+ runner.run('nice mkfs %s -t %s -q %s -L %s'
+ % (force, fstype, self.testrootfs_path, self.testrootfs_label), timeout=1800)
runner.run('umount %s' % self.testboot_path, failok=True)
runner.run('nice mkfs.vfat %s -n %s' % (self.testboot_path, self.testboot_label))
@@ -419,7 +424,8 @@ class MasterImageTarget(Target):
boot_cmds = self._load_boot_cmds(default='boot_cmds_master',
boot_tags=self.master_boot_tags)
self._customize_bootloader(self.proc, boot_cmds)
- self.proc.expect(self.config.image_boot_msg, timeout=300)
+ self.proc.expect(self.config.image_boot_msg,
+ timeout=self.config.image_boot_msg_timeout)
self._auto_login(self.proc, is_master=True)
self._wait_for_prompt(self.proc, self.config.master_str, timeout=300)
@@ -538,7 +544,7 @@ class MasterImageTarget(Target):
def _deploy_linaro_android_data(self, session, datatbz2):
data_label, data_path = self._android_data_label(session)
session.run('umount %s' % data_path, failok=True)
- session.run('nice mkfs.ext4 -q %s -L %s' %
+ session.run('nice mkfs.ext4 -F -q %s -L %s' %
(data_path, data_label))
session.run('udevadm trigger')
session.run('mkdir -p /mnt/lava/data')
diff --git a/lava_dispatcher/device/target.py b/lava_dispatcher/device/target.py
index 83a4194..f4bd36d 100644
--- a/lava_dispatcher/device/target.py
+++ b/lava_dispatcher/device/target.py
@@ -467,7 +467,8 @@ class Target(object):
connection.empty_buffer()
def _enter_bootloader(self, connection):
- if connection.expect(self.config.interrupt_boot_prompt) != 0:
+ if connection.expect(self.config.interrupt_boot_prompt,
+ timeout=self.config.bootloader_timeout) != 0:
raise Exception("Failed to enter bootloader")
if self.config.interrupt_boot_control_character:
connection.sendcontrol(self.config.interrupt_boot_control_character)
diff --git a/lava_dispatcher/device/vexpress.py b/lava_dispatcher/device/vexpress.py
index 466d300..32865a4 100644
--- a/lava_dispatcher/device/vexpress.py
+++ b/lava_dispatcher/device/vexpress.py
@@ -1,6 +1,8 @@
# Copyright (C) 2013 Linaro Limited
#
# Author: Antonio Terceiro <antonio.terceiro@linaro.org>
+# Author: Dave Pigott <dave.pigott@linaro.org>
+# Author: Tyler Baker <tyler.baker@linaro.org>
#
# This file is part of LAVA Dispatcher.
#
@@ -24,56 +26,114 @@ import logging
from time import sleep
from contextlib import contextmanager
-from lava_dispatcher.device.master import MasterImageTarget
+from lava_dispatcher.device.bootloader import BootloaderTarget
+from lava_dispatcher.utils import extract_tar
+from lava_dispatcher.downloader import (
+ download_image,
+)
from lava_dispatcher.errors import (
CriticalError,
OperationFailed,
)
-class VexpressTarget(MasterImageTarget):
+class VexpressTarget(BootloaderTarget):
def __init__(self, context, config):
super(VexpressTarget, self).__init__(context, config)
self.test_uefi = None
-
- if (self.config.uefi_image_filename is None or
- self.config.vexpress_uefi_path is None or
- self.config.vexpress_uefi_backup_path is None or
- self.config.vexpress_usb_mass_storage_device is None):
-
- raise CriticalError(
- "Versatile Express devices must specify all "
- "of the following configuration variables: "
- "uefi_image_filename, vexpress_uefi_path, "
- "vexpress_uefi_backup_path, and "
- "vexpress_usb_mass_storage_device")
+ self.test_bl1 = None
+
+ if self.config.vexpress_requires_trusted_firmware:
+ if (self.config.vexpress_bl1_image_filename is None or
+ self.config.vexpress_bl1_image_files is None or
+ self.config.vexpress_uefi_image_filename is None or
+ self.config.vexpress_uefi_image_files is None or
+ self.config.vexpress_bl1_path is None or
+ self.config.vexpress_bl1_backup_path is None or
+ self.config.vexpress_uefi_path is None or
+ self.config.vexpress_uefi_backup_path is None or
+ self.config.vexpress_usb_mass_storage_device is None):
+
+ raise CriticalError(
+ "Versatile Express devices that use "
+ "trusted firmware must specify all "
+ "of the following configuration variables: "
+ "vexpress_bl1_image_filename, vexpress_bl1_image_files, "
+ "vexpress_uefi_image_filename, vexpress_uefi_image_files, "
+ "vexpress_bl1_path, vexpress_bl1_backup_path "
+ "vexpress_uefi_path, vexpress_uefi_backup_path and "
+ "vexpress_usb_mass_storage_device")
+ else:
+ if (self.config.vexpress_uefi_image_filename is None or
+ self.config.vexpress_uefi_image_files is None or
+ self.config.vexpress_uefi_path is None or
+ self.config.vexpress_uefi_backup_path is None or
+ self.config.vexpress_usb_mass_storage_device is None):
+
+ raise CriticalError(
+ "Versatile Express devices must specify all "
+ "of the following configuration variables: "
+ "vexpress_uefi_image_filename, vexpress_uefi_image_files, "
+ "vexpress_uefi_path, vexpress_uefi_backup_path and "
+ "vexpress_usb_mass_storage_device")
##################################################################
- # methods inherited from MasterImageTarget and overriden here
+ # methods inherited from BootloaderTarget and overriden here
##################################################################
+ def deploy_linaro_kernel(self, kernel, ramdisk, dtb, modules, rootfs,
+ nfsrootfs, bootloader, firmware, bl1, bl2,
+ bl31, rootfstype, bootloadertype, target_type):
+ if bootloader is None:
+ if self.config.vexpress_uefi_default is None:
+ raise CriticalError("UEFI image is required")
+ else:
+ self.test_uefi = download_image(self.config.vexpress_uefi_default, self.context,
+ self._tmpdir,
+ decompress=False)
+ else:
+ self.test_uefi = download_image(bootloader, self.context,
+ self._tmpdir,
+ decompress=False)
+ bootloader = None
+
+ if bl1 is None and self.config.vexpress_requires_trusted_firmware:
+ if self.config.vexpress_bl1_default is None:
+ raise CriticalError("BL1 firmware is required")
+ else:
+ self.test_bl1 = download_image(self.config.vexpress_bl1_default, self.context,
+ self._tmpdir,
+ decompress=False)
+ else:
+ self.test_bl1 = download_image(bl1, self.context,
+ self._tmpdir,
+ decompress=False)
+ bl1 = None
+
+ super(VexpressTarget, self).deploy_linaro_kernel(kernel, ramdisk, dtb, modules, rootfs,
+ nfsrootfs, bootloader, firmware, bl1, bl2,
+ bl31, rootfstype, bootloadertype, target_type)
+
def _load_test_firmware(self):
with self._mcc_setup() as mount_point:
- self._install_test_uefi(mount_point)
+ self._install_test_firmware(mount_point)
def _load_master_firmware(self):
with self._mcc_setup() as mount_point:
- self._restore_uefi_backup(mount_point)
+ self._restore_firmware_backup(mount_point)
def _deploy_android_tarballs(self, master, boot, system, data):
super(VexpressTarget, self)._deploy_android_tarballs(master, boot,
system, data)
# android images have boot files inside boot/ in the tarball
- uefi_on_image = os.path.join('boot', self.config.uefi_image_filename)
- self._extract_uefi_from_tarball(boot, uefi_on_image)
+ self._extract_firmware_from_tarball(boot)
def _deploy_tarballs(self, boot_tgz, root_tgz, rootfstype):
super(VexpressTarget, self)._deploy_tarballs(boot_tgz, root_tgz,
rootfstype)
- uefi_on_image = self.config.uefi_image_filename
- self._extract_uefi_from_tarball(boot_tgz, uefi_on_image)
+ self._extract_firmware_from_tarball(boot_tgz)
##################################################################
# implementation-specific methods
@@ -158,23 +218,20 @@ class VexpressTarget(MasterImageTarget):
def _leave_mcc(self):
self.proc.sendline("reboot")
- def _extract_uefi_from_tarball(self, tarball, uefi_on_image):
- tmpdir = self.scratch_dir
+ def _extract_firmware_from_tarball(self, tarball):
- # Android boot tarballs have the UEFI binary at boot/*.bin, while
- # Ubuntu ones have it at ./*.bin
- #
- # --no-anchored matches the name inside any directory in the tarball.
- self.context.run_command('tar --no-anchored -xaf %s -C %s %s' % (tarball, tmpdir,
- uefi_on_image))
+ extract_tar(tarball, self.scratch_dir)
- uefi_on_image = os.path.join(tmpdir, uefi_on_image)
- test_uefi = os.path.join(tmpdir, 'uefi.bin')
- self.context.run_command('mv %s %s' % (uefi_on_image, test_uefi))
+ if self.config.vexpress_requires_trusted_firmware:
+ self.test_bl1 = self._copy_first_find_from_list(self.scratch_dir, self.scratch_dir,
+ self.config.vexpress_bl1_image_files,
+ self.config.vexpress_bl1_image_filename)
- self.test_uefi = test_uefi
+ self.test_uefi = self._copy_first_find_from_list(self.scratch_dir, self.scratch_dir,
+ self.config.vexpress_uefi_image_files,
+ self.config.vexpress_uefi_image_filename)
- def _restore_uefi_backup(self, mount_point):
+ def _restore_firmware_backup(self, mount_point):
uefi_path = self.config.vexpress_uefi_path
uefi = os.path.join(mount_point, uefi_path)
uefi_backup_path = self.config.vexpress_uefi_backup_path
@@ -188,12 +245,37 @@ class VexpressTarget(MasterImageTarget):
# the uefi in there is the good one, and we backup it up.
self.context.run_command_with_retries('cp %s %s' % (uefi, uefi_backup))
- def _install_test_uefi(self, mount_point):
+ if self.config.vexpress_requires_trusted_firmware:
+ bl1_path = self.config.vexpress_bl1_path
+ bl1 = os.path.join(mount_point, bl1_path)
+ bl1_backup_path = self.config.vexpress_bl1_backup_path
+ bl1_backup = os.path.join(mount_point, bl1_backup_path)
+
+ if os.path.exists(bl1_backup):
+ # restore the firmware backup
+ self.context.run_command_with_retries('cp %s %s' % (bl1_backup, bl1))
+ else:
+ # no existing backup yet means that this is the first time ever;
+ # the firmware in there is the good one, and we backup it up.
+ self.context.run_command_with_retries('cp %s %s' % (bl1, bl1_backup))
+
+ def _install_test_firmware(self, mount_point):
uefi_path = self.config.vexpress_uefi_path
uefi = os.path.join(mount_point, uefi_path)
- # FIXME what if self.test_uefi is not set, or points to an unexisting
- # file?
- self.context.run_command('cp %s %s' % (self.test_uefi, uefi))
+
+ if os.path.exists(self.test_uefi):
+ self.context.run_command('cp %s %s' % (self.test_uefi, uefi))
+ else:
+ raise CriticalError("No path to uefi firmware")
+
+ if self.config.vexpress_requires_trusted_firmware:
+ bl1_path = self.config.vexpress_bl1_path
+ bl1 = os.path.join(mount_point, bl1_path)
+
+ if os.path.exists(self.test_bl1):
+ self.context.run_command('cp %s %s' % (self.test_bl1, bl1))
+ else:
+ raise CriticalError("No path to bl1 firmware")
target_class = VexpressTarget
diff --git a/lava_dispatcher/device/wg.py b/lava_dispatcher/device/wg.py
deleted file mode 100644
index 40b4c2b..0000000
--- a/lava_dispatcher/device/wg.py
+++ /dev/null
@@ -1,225 +0,0 @@
-# Copyright (C) 2014 Linaro Limited
-#
-# Author: Dave Pigott <dave.pigott@linaro.org>
-#
-# This file is part of LAVA Dispatcher.
-#
-# LAVA Dispatcher is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# LAVA Dispatcher is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along
-# with this program; if not, see <http://www.gnu.org/licenses>.
-
-import pexpect
-import os
-import logging
-from time import sleep
-from contextlib import contextmanager
-
-from lava_dispatcher.device.master import MasterImageTarget
-from lava_dispatcher.utils import extract_tar
-from lava_dispatcher.errors import (
- CriticalError,
- OperationFailed,
-)
-
-
-class WGTarget(MasterImageTarget):
-
- def __init__(self, context, config):
- super(WGTarget, self).__init__(context, config)
-
- self.test_bl1 = None
- self.test_fip = None
-
- if (self.config.bl1_image_filename is None or
- self.config.bl1_image_files is None or
- self.config.fip_image_filename is None or
- self.config.fip_image_files is None or
- self.config.wg_bl1_path is None or
- self.config.wg_bl1_backup_path is None or
- self.config.wg_fip_path is None or
- self.config.wg_fip_backup_path is None or
- self.config.wg_usb_mass_storage_device is None):
-
- raise CriticalError(
- "WG devices must specify all "
- "of the following configuration variables: "
- "bl1_image_filename, bl1_image_files, "
- "fip_image_filename, fip_image_files, "
- "wg_bl1_path, wg_bl1_bacup_path "
- "wg_fip_path, wg_fip backup_path "
- "wg_usb_mass_storage_device")
-
- ##################################################################
- # methods inherited from MasterImageTarget and overriden here
- ##################################################################
-
- def _load_test_firmware(self):
- with self._mcc_setup() as mount_point:
- self._install_test_firmware(mount_point)
-
- def _load_master_firmware(self):
- with self._mcc_setup() as mount_point:
- self._restore_firmware_backup(mount_point)
-
- def _deploy_android_tarballs(self, master, boot, system, data):
- super(WGTarget, self)._deploy_android_tarballs(master, boot,
- system, data)
- # android images have boot files inside boot/ in the tarball
- self._extract_firmware_from_tarball(boot)
-
- def _deploy_tarballs(self, boot_tgz, root_tgz, rootfstype):
- super(WGTarget, self)._deploy_tarballs(boot_tgz, root_tgz,
- rootfstype)
- self._extract_firmware_from_tarball(boot_tgz)
-
- ##################################################################
- # implementation-specific methods
- ##################################################################
-
- @contextmanager
- def _mcc_setup(self):
- """
- This method will manage the context for manipulating the USB mass
- storage device, and pass the mount point where the USB MSD is mounted
- to the inner block.
-
- Example:
-
- with self._mcc_setup() as mount_point:
- do_stuff_with(mount_point)
-
-
- This can be used for example to copy files from/to the USB MSD.
- Mounting and unmounting is managed by this method, so the inner block
- does not have to handle that.
- """
-
- mount_point = os.path.join(self.scratch_dir, 'wg-usb')
- if not os.path.exists(mount_point):
- os.makedirs(mount_point)
-
- self._enter_mcc()
- self._mount_usbmsd(mount_point)
- try:
- yield mount_point
- finally:
- self._umount_usbmsd(mount_point)
- self._leave_mcc()
-
- def _enter_mcc(self):
- match_id = self.proc.expect([
- self.config.wg_stop_autoboot_prompt,
- pexpect.EOF, pexpect.TIMEOUT], timeout=120)
- if match_id != 0:
- msg = 'Unable to intercept MCC boot prompt'
- logging.error(msg)
- raise OperationFailed(msg)
- self.proc.sendline("")
- match_id = self.proc.expect([
- 'Cmd>',
- pexpect.EOF, pexpect.TIMEOUT], timeout=120)
- if match_id != 0:
- msg = 'MCC boot prompt not found'
- logging.error(msg)
- raise OperationFailed(msg)
-
- def _mount_usbmsd(self, mount_point):
- self.proc.sendline("USB_ON")
- self.proc.expect(['Cmd>'])
-
- # wait a few seconds so that the kernel on the host detects the USB
- # mass storage interface exposed by the WG
- sleep(5)
-
- usb_device = self.config.wg_usb_mass_storage_device
-
- # Try to mount the MMC device. If we detect a failure when mounting. Toggle
- # the USB MSD interface, and try again. If we fail again, raise an OperationFailed
- # except to retry to the boot process.
- if self.context.run_command('mount %s %s' % (usb_device, mount_point)) != 0:
- self.proc.sendline("USB_OFF")
- self.proc.expect(['Cmd>'])
- self.proc.sendline("USB_ON")
- self.proc.expect(['Cmd>'])
- sleep(5)
- if self.context.run_command('mount %s %s' % (usb_device, mount_point)) != 0:
- msg = "Failed to mount MMC on host"
- logging.exception(msg)
- raise OperationFailed(msg)
-
- def _umount_usbmsd(self, mount_point):
- self.context.run_command_with_retries('umount %s' % mount_point)
- self.proc.sendline("USB_OFF")
- self.proc.expect(['Cmd>'])
-
- def _leave_mcc(self):
- self.proc.sendline("reboot")
-
- def _extract_firmware_from_tarball(self, tarball):
-
- extract_tar(tarball, self.scratch_dir)
-
- self.test_bl1 = self._copy_first_find_from_list(self.scratch_dir, self.scratch_dir,
- self.config.bl1_image_files,
- self.config.bl1_image_filename)
-
- self.test_fip = self._copy_first_find_from_list(self.scratch_dir, self.scratch_dir,
- self.config.fip_image_files,
- self.config.fip_image_filename)
-
- def _restore_firmware_backup(self, mount_point):
- bl1_path = self.config.wg_bl1_path
- bl1 = os.path.join(mount_point, bl1_path)
- bl1_backup_path = self.config.wg_bl1_backup_path
- bl1_backup = os.path.join(mount_point, bl1_backup_path)
-
- if os.path.exists(bl1_backup):
- # restore the firmware backup
- self.context.run_command_with_retries('cp %s %s' % (bl1_backup, bl1))
- else:
- # no existing backup yet means that this is the first time ever;
- # the firmware in there is the good one, and we backup it up.
- self.context.run_command_with_retries('cp %s %s' % (bl1, bl1_backup))
-
- fip_path = self.config.wg_fip_path
- fip = os.path.join(mount_point, fip_path)
- fip_backup_path = self.config.wg_fip_backup_path
- fip_backup = os.path.join(mount_point, fip_backup_path)
-
- if os.path.exists(fip_backup):
- # restore the firmware backup
- self.context.run_command_with_retries('cp %s %s' % (fip_backup, fip))
- else:
- # no existing backup yet means that this is the first time ever;
- # the firmware in there is the good one, and we backup it up.
- self.context.run_command_with_retries('cp %s %s' % (fip, fip_backup))
-
- def _install_test_firmware(self, mount_point):
- bl1_path = self.config.wg_bl1_path
- bl1 = os.path.join(mount_point, bl1_path)
-
- if os.path.exists(self.test_bl1):
- self.context.run_command('cp %s %s' % (self.test_bl1, bl1))
- else:
- raise CriticalError("No path to bl1 firmware")
-
- fip_path = self.config.wg_fip_path
- fip = os.path.join(mount_point, fip_path)
-
- if os.path.exists(self.test_fip):
- self.context.run_command('cp %s %s' % (self.test_fip, fip))
- else:
- raise CriticalError("No path to fip firmware")
-
-
-target_class = WGTarget
diff --git a/lava_dispatcher/downloader.py b/lava_dispatcher/downloader.py
index f2f66f8..860d6a4 100644
--- a/lava_dispatcher/downloader.py
+++ b/lava_dispatcher/downloader.py
@@ -60,14 +60,31 @@ def _http_stream(url, proxy=None, cookies=None):
handlers = []
if proxy:
handlers = [urllib2.ProxyHandler({'http': '%s' % proxy})]
+
+ if url.username is not None and url.password is not None:
+ # HACK, urllib2 doesn't like urls with username and pass
+ # fix this in the refactoring with requests support.
+ url_string = urlparse.urlunparse([
+ url.scheme,
+ url.netloc.partition("@")[2],
+ url.path,
+ url.params,
+ url.query,
+ url.fragment])
+ passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
+ passmgr.add_password(None, url_string, url.username, url.password)
+ handlers.append(urllib2.HTTPBasicAuthHandler(passmgr))
+ else:
+ url_string = url.geturl()
+
opener = urllib2.build_opener(*handlers)
if cookies:
opener.addheaders.append(('Cookie', cookies))
try:
- url = urllib2.quote(url.geturl(), safe=":/")
- resp = opener.open(url, timeout=30)
+ url_quoted = urllib2.quote(url_string, safe=":/")
+ resp = opener.open(url_quoted, timeout=30)
yield resp
finally:
if resp:
diff --git a/lava_dispatcher/job.py b/lava_dispatcher/job.py
index 1dbc1fd..7d71750 100644
--- a/lava_dispatcher/job.py
+++ b/lava_dispatcher/job.py
@@ -282,6 +282,7 @@ class LavaTestJob(object):
validate_job_data(self.job_data)
self._set_logging_level()
lava_commands = get_all_cmds()
+ lmp_init_data = []
if self.job_data['actions'][-1]['command'].startswith(
"submit_results"):
@@ -340,12 +341,16 @@ class LavaTestJob(object):
else:
logging.debug("[ACTION-B] Single node test!")
+ # get LMP init data, if it exists.
if 'lmp_module' in self.job_data:
- metadata['lmp_module'] = json.dumps(self.job_data['lmp_module'])
+ lmp_init_data = self.job_data['lmp_module']
+ metadata['lmp_module'] = json.dumps(lmp_init_data)
self.context.test_data.add_metadata(metadata)
- # init LMP module
- lmp_init_boards.init(self.job_data['lmp_module'],
- self.context.device_config)
+ # integrate LMP init data to LMP default config
+ lmp_init_data = lmp_init_boards.data_integrate(lmp_init_data, self.context.device_config)
+ # init LMP module, if necessary
+ if lmp_init_data is not []:
+ lmp_init_boards.init(lmp_init_data, self.context.device_config)
def term_handler(signum, frame):
self.context.finish()
diff --git a/lava_dispatcher/pipeline/action.py b/lava_dispatcher/pipeline/action.py
index 8f4d4d2..55b8625 100644
--- a/lava_dispatcher/pipeline/action.py
+++ b/lava_dispatcher/pipeline/action.py
@@ -21,6 +21,7 @@
import os
import sys
import time
+import signal
import types
import yaml
import logging
@@ -104,6 +105,7 @@ class Pipeline(object):
self.job = parent.job
def _check_action(self, action):
+ # FIXME: this should be a method from the Action class
if not action or not issubclass(type(action), Action):
raise RuntimeError("Only actions can be added to a pipeline: %s" % action)
if not action:
@@ -117,6 +119,7 @@ class Pipeline(object):
self._check_action(action)
self.actions.append(action)
action.level = "%s.%s" % (self.branch_level, len(self.actions))
+ # FIXME: if this is only happening in unit test, this has to be fixed later on
if self.job: # should only be None inside the unit tests
action.job = self.job
if self.parent: # action
@@ -130,11 +133,14 @@ class Pipeline(object):
self.job.parameters['output_dir'],
"%s-%s.log" % (action.level, action.name)
)
+ if not os.path.exists(os.path.dirname(yaml_filename)):
+ os.makedirs(os.path.dirname(yaml_filename))
action.log_handler = logging.FileHandler(yaml_filename, mode='a', encoding="utf8")
# per action loggers always operate in DEBUG mode - the frontend does the parsing later.
action.log_handler.setLevel(logging.DEBUG)
# yaml wrapper inside the log handler
- action.log_handler.setFormatter(logging.Formatter('id: "<LAVA_DISPATCHER>%(asctime)s"\n%(message)s'))
+ pattern = ' - id: "<LAVA_DISPATCHER>%(asctime)s"\n%(message)s'
+ action.log_handler.setFormatter(logging.Formatter(pattern))
# if the action has an internal pipeline, initialise that here.
action.populate()
@@ -171,8 +177,13 @@ class Pipeline(object):
def run_actions(self, connection, args=None):
for action in self.actions:
+ # TODO: moving all logger.getLogger at the top of each file (at
+ # import time). Isn't it better to have one logger per action and
+ # to create these loggers at creation time.
yaml_log = None
std_log = logging.getLogger("ASCII")
+ # FIXME: this is not related to the log_handler. It's a side effect
+ # that the log_handkler does create the output directory.
if not action.log_handler:
# FIXME: unit test needed
# if no output dir specified in the job
@@ -184,7 +195,10 @@ class Pipeline(object):
yaml_log.addHandler(action.log_handler)
yaml_log.debug({'start': {action.level: action.name}})
try:
+ start = time.time()
new_connection = action.run(connection, args)
+ action.elapsed_time = time.time() - start
+ action._log("duration: %.02f" % action.elapsed_time)
if new_connection:
connection = new_connection
except KeyboardInterrupt:
@@ -242,7 +256,9 @@ class Action(object):
self.log_handler = None
self.job = None
self.results = None
+ # FIXME: what about {} for default value?
self.env = None # FIXME make this a parameter which gets default value when first called
+ self.timeout = None # Timeout class instance, if needed.
# public actions (i.e. those who can be referenced from a job file) must
# declare a 'class-type' name so they can be looked up.
@@ -264,6 +280,7 @@ class Action(object):
def description(self, description):
self.__set_desc__(description)
+ # FIXME: dwhy do you need this function?
def __set_desc__(self, desc):
self.__description__ = desc
@@ -282,6 +299,7 @@ class Action(object):
def summary(self, summary):
self.__set_summary__(summary)
+ # FIXME: dwhy do you need this function?
def __set_summary__(self, summary):
self.__summary__ = summary
@@ -301,6 +319,7 @@ class Action(object):
"""
self.job.context.pipeline_data.update(value)
+ # FIXME: has to be called select to be consistent with Deployment
@classmethod
def find(cls, name):
for subclass in cls.__subclasses__():
@@ -339,6 +358,7 @@ class Action(object):
def level(self, value):
self.__set_level__(value)
+ # FIXME: dwhy do you need this function?
def __set_level__(self, value):
self.__level__ = value
@@ -410,9 +430,15 @@ class Action(object):
def _log(self, message):
if not message:
return
+ # FIXME: why are we recreating the loggers everytime? Maybe having one
+ # logger per action si easier to use. Calling it YAML.%(action_name)s
yaml_log = logging.getLogger("YAML")
std_log = logging.getLogger("ASCII")
- yaml_log.debug({"output": message.split('\n')})
+ if type(message) is dict:
+ for key, value in message.iteritems():
+ yaml_log.debug(" %s: %s" % (key, value))
+ else:
+ yaml_log.debug(" log: \"%s\"" % message)
std_log.info(message)
def _run_command(self, command_list, env=None):
@@ -423,9 +449,11 @@ class Action(object):
and strip embedded newlines / whitespace where practical.
Returns the output of the command (after logging the output)
Includes default support for proxy settings in the environment.
+ Blocks until the command returns then processes & logs the output.
"""
if type(command_list) != list:
raise RuntimeError("commands to _run_command need to be a list")
+ # FIXME: see logger
yaml_log = logging.getLogger("YAML")
log = None
if not self.env:
@@ -480,9 +508,11 @@ class Action(object):
if self.err:
print self.err
"""
+ # FIXME: should be "raise NotImplementedError"
pass
def cleanup(self):
+ # FIXME: perform() does not exist, is it run()?
"""
This method *will* be called after perform(), no matter whether
perform() raises an exception or not. It should cleanup any resources
@@ -493,9 +523,10 @@ class Action(object):
- error codes
- etc
"""
+ # FIXME: should be "raise NotImplementedError"
try:
raise
- except:
+ except: # pylint: disable=bare-except
sys.exc_clear()
def post_process(self):
@@ -507,6 +538,7 @@ class Action(object):
In this classs this method does nothing. It must be implemented by
subclasses
"""
+ # FIXME: should be "raise NotImplementedError"
pass
def explode(self):
@@ -522,12 +554,21 @@ class Action(object):
content = getattr(self, name)
if name == "job" or name == "log_handler" or name == "internal_pipeline":
continue
+ if name == "timeout":
+ if content and not getattr(content, 'protected'):
+ content = {
+ 'name': getattr(content, 'name'),
+ 'duration': getattr(content, 'duration')
+ }
if name == 'parameters':
- # FIXME: implement the handling of parameters to be serialisable
+ # FIXME: move deployment_data into the Job to save on repetition. Then output alongside the Device in Pipeline.
if 'deployment_data' in content:
- del content['deployment_data']
- import json
- content = json.dumps(content)
+ content = {
+ 'deployment_data': content['deployment_data'].__data__
+ }
+ else:
+ output = {'parameters': content}
+ content = output
if isinstance(content, types.MethodType):
continue
if content:
@@ -540,6 +581,8 @@ class RetryAction(Action):
def __init__(self):
super(RetryAction, self).__init__()
self.retries = 0
+ # FIXME: have better dafault values. Should be seen somewhere in the
+ # configuration or a constant in the code.
self.max_retries = 5
self.sleep = 1
@@ -549,13 +592,16 @@ class RetryAction(Action):
new_connection = self.run(connection)
return new_connection
except KeyboardInterrupt:
+ # FIXME: calling cleanup two times!
self.cleanup()
self.err = "\rCancel" # Set a useful message.
except (JobError, InfrastructureError):
+ # FIXME: print the retry cont like %(current_retry)d/%(max_retry)d
self._log("%s failed, trying again" % self.name)
self.retries += 1
time.sleep(self.sleep)
finally:
+ # QUESTION: is it the right time to cleanup?
self.cleanup()
raise JobError("%s retries failed for %s" % (self.retries, self.name))
@@ -563,12 +609,32 @@ class RetryAction(Action):
self.run(connection)
-class Deployment(object):
+class FinalizeAction(Action):
+
+ def __init__(self):
+ super(FinalizeAction, self).__init__()
+ self.name = "finalize"
+ self.summary = "finalize the job"
+ self.description = "finish the process and cleanup"
+
+ def run(self, connection, args=None):
+ """
+ The pexpect.spawn here is the ShellCommand not the ShellSession connection object.
+ So call the finalise() function of the connection which knows about the raw_connection inside.
+ """
+ if connection:
+ connection.finalise()
+
+
+class Deployment(object): # pylint: disable=abstract-class-not-used
"""
- Deployment is a strategy class which aggregates Actions
+ Deployment is a strategy class which aggregates Actions
until the request from the YAML can be validated or rejected.
Translates the parsed pipeline into Actions and populates
each Action with parameters.
+ Primary purpose of the Deployment class is to allow the
+ parser to select the correct deployment before initialising
+ any Actions.
"""
priority = 0
@@ -629,7 +695,7 @@ class Deployment(object):
self.__set_parameters__(data)
@classmethod
- def accepts(cls, device, parameters):
+ def accepts(cls, device, parameters): # pylint: disable=unused-argument
"""
Returns True if this deployment strategy can be used the the
given device and details of an image in the parameters.
@@ -647,7 +713,92 @@ class Deployment(object):
if len(willing) == 0:
raise NotImplementedError(
"No deployment strategy available for the given "
- "device '%s'." % device.config.hostname)
+ "device '%s'." % device.parameters['hostname'])
+
+ # higher priority first
+ compare = lambda x, y: cmp(y.priority, x.priority)
+ prioritized = sorted(willing, compare)
+
+ return prioritized[0]
+
+
+class Boot(object):
+ """
+ Allows selection of the boot method for this job within the parser.
+ """
+
+ priority = 0
+
+ def __init__(self, parent):
+ self.__parameters__ = {}
+ self.pipeline = parent
+ self.job = parent.job
+
+ @classmethod
+ def accepts(cls, device, parameters): # pylint: disable=unused-argument
+ """
+ Returns True if this deployment strategy can be used the the
+ given device and details of an image in the parameters.
+
+ Must be implemented by subclasses.
+ """
+ return NotImplementedError("accepts")
+
+ @classmethod
+ def select(cls, device, parameters):
+ candidates = cls.__subclasses__()
+ willing = [c for c in candidates if c.accepts(device, parameters)]
+ if len(willing) == 0:
+ raise NotImplementedError(
+ "No boot strategy available for the device "
+ "'%s' with the specified job parameters" % device.parameters['hostname']
+ )
+
+ # higher priority first
+ compare = lambda x, y: cmp(y.priority, x.priority)
+ prioritized = sorted(willing, compare)
+
+ return prioritized[0]
+
+
+class LavaTest(object): # pylint: disable=abstract-class-not-used
+ """
+ Allows selection of the boot method for this job within the parser.
+ """
+
+ priority = 0
+
+ def __init__(self, parent):
+ self.__parameters__ = {}
+ self.pipeline = parent
+ self.job = parent.job
+
+ @contextmanager
+ def boot(self):
+ """
+ This method must be implemented by subclasses.
+ """
+ raise NotImplementedError("test")
+
+ @classmethod
+ def accepts(cls, device, parameters): # pylint: disable=unused-argument
+ """
+ Returns True if this deployment strategy can be used the the
+ given device and details of an image in the parameters.
+
+ Must be implemented by subclasses.
+ """
+ return NotImplementedError("accepts")
+
+ @classmethod
+ def select(cls, device, parameters):
+ candidates = cls.__subclasses__()
+ willing = [c for c in candidates if c.accepts(device, parameters)]
+ if len(willing) == 0:
+ raise NotImplementedError(
+ "No test strategy available for the device "
+ "'%s' with the specified job parameters" % device.parameters['hostname']
+ )
# higher priority first
compare = lambda x, y: cmp(y.priority, x.priority)
@@ -656,7 +807,7 @@ class Deployment(object):
return prioritized[0]
-class Image(object):
+class Image(object): # pylint: disable=abstract-class-not-used
"""
Create subclasses for each type of image: prebuilt, hwpack+rootfs,
kernel+rootfs+dtb+..., dummy, ...
@@ -671,12 +822,66 @@ class Image(object):
raise NotImplementedError("mount_rootfs")
-class Connection(object):
+class Timeout(object):
+ """
+ The Timeout class is a declarative base which any actions can use. If an Action has
+ a timeout, that timeout name and the duration will be output as part of the action
+ description and the timeout is then exposed as a modifiable value via the device_type,
+ device or even job inputs. (Some timeouts may be deemed "protected" which may not be
+ altered by the job. All timeouts are subject to a hardcoded maximum duration which
+ cannot be exceeded by device_type, device or job input, only by the Action initialising
+ the timeout.
+ """
+
+ def __init__(self, name, duration=30, protected=False):
+ self.name = name
+ self.duration = duration # Actions can set timeouts higher than the clamp.
+ self.protected = protected
+ @classmethod
+ def default_duration(cls):
+ return 30
+
+ def modify(self, duration):
+ """
+ Called from the parser if the job or device YAML wants to set an override.
+ """
+ if self.protected:
+ raise JobError("Trying to modify a protected timeout: %s.", self.name)
+ clamp = lambda n, minn, maxn: max(min(maxn, n), minn)
+ self.duration = clamp(duration, 1, 300)
+
+
+class Connection(object):
+ """
+ A raw_connection is an arbitrary instance of a standard Python (or added LAVA) class
+ designed to implement an interactive connection onto the device. The raw_connection
+ needs to be able to send commands, use a timeout, handle errors, log the output,
+ match on regular expressions for the output, report the pid of the spawned process
+ and cause the spawned process to close/terminate.
+ The current implementation uses a pexpect.spawn wrapper. For a standard Shell
+ connection, that is the ShellCommand class.
+ Each different wrapper of pexpect.spawn (and any other wrappers later designed)
+ needs to be a separate class supported by another class inheriting from Connection.
+ """
def __init__(self, device, raw_connection):
self.device = device
self.raw_connection = raw_connection
+ def sendline(self, line):
+ self.raw_connection.sendline(line)
+
+ def finalise(self):
+ if self.raw_connection:
+ yaml_log = logging.getLogger("YAML")
+ try:
+ os.killpg(self.raw_connection.pid, signal.SIGKILL)
+ yaml_log.debug("Finalizing child process group with PID %d" % self.raw_connection.pid)
+ except OSError:
+ connection.kill(9)
+ yaml_log.debug("Finalizing child process with PID %d" % self.raw_connection.pid)
+ self.raw_connection.close()
+
class Device(object):
"""
diff --git a/lava_dispatcher/pipeline/actions/boot/__init__.py b/lava_dispatcher/pipeline/actions/boot/__init__.py
index 06c0a75..06093c0 100644
--- a/lava_dispatcher/pipeline/actions/boot/__init__.py
+++ b/lava_dispatcher/pipeline/actions/boot/__init__.py
@@ -35,3 +35,12 @@ class BootAction(Action):
"""
name = 'boot'
+
+
+class AutoLoginAction(Action):
+
+ def __init__(self):
+ super(AutoLoginAction, self).__init__()
+ self.name = 'auto-login-action'
+ self.description = "automatically login after boot using job parameters"
+ self.summary = "Auto-login after boot"
diff --git a/lava_dispatcher/pipeline/actions/boot/kvm.py b/lava_dispatcher/pipeline/actions/boot/kvm.py
new file mode 100644
index 0000000..d51232b
--- /dev/null
+++ b/lava_dispatcher/pipeline/actions/boot/kvm.py
@@ -0,0 +1,131 @@
+# Copyright (C) 2014 Linaro Limited
+#
+# Author: Neil Williams <neil.williams@linaro.org>
+#
+# This file is part of LAVA Dispatcher.
+#
+# LAVA Dispatcher is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# LAVA Dispatcher is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along
+# with this program; if not, see <http://www.gnu.org/licenses>.
+
+import os
+import sys
+from lava_dispatcher.pipeline.action import (
+ Boot,
+ Pipeline,
+ InfrastructureError,
+ Timeout,
+ JobError
+)
+from lava_dispatcher.pipeline.actions.boot import BootAction, AutoLoginAction
+from lava_dispatcher.pipeline.shell import ExpectShellSession, ShellCommand, ShellSession
+
+
+class BootKVM(Boot):
+ """
+ The Boot method prepares the command to run on the dispatcher but this
+ command needs to start a new connection and then allow AutoLogin, if
+ enabled, and then expect a shell session which can be handed over to the
+ test method. self._run_command is a blocking call, so Boot needs to use
+ a direct spawn call via ShellCommand (which wraps pexpect.spawn) then
+ hand this pexpect wrapper to subsequent actions as a shell connection.
+ """
+
+ def __init__(self, parent):
+ super(BootKVM, self).__init__(parent)
+ self.action = BootQEMUImageAction()
+ self.action.job = self.job
+ parent.add_action(self.action)
+
+ internal_pipeline = Pipeline(parent=self.action, job=self.job)
+ if 'auto_login' in self.action.parameters:
+ internal_pipeline.add_action(AutoLoginAction())
+ internal_pipeline.add_action(ExpectShellSession())
+
+ @classmethod
+ def accepts(cls, device, parameters):
+ # FIXME: needs to do more work with job parameters before accepting
+ if hasattr(device, 'config'):
+ if device.config.device_type == 'kvm': # FIXME: teach base unit tests to use new style Device objects
+ return True
+ else:
+ if device.parameters['device_type'] == 'kvm': # FIXME: device_type should likely be qemu - see also deploy
+ return True
+ return False
+
+
+class BootQEMUImageAction(BootAction):
+
+ def __init__(self):
+ super(BootQEMUImageAction, self).__init__()
+ self.name = 'boot_qemu_image'
+ self.description = "boot image using QEMU command line"
+ self.summary = "boot QEMU image"
+ self.overrides = None
+ self.command = []
+ self.timeout = Timeout(self.name) # FIXME: decide on a duration for the boot QEMU Image timeout
+
+ # FIXME: move into a new utils module?
+ def _find(self, path, match=os.path.isfile):
+ """
+ Simple replacement for the `which` command found on
+ Debian based systems.
+ """
+ for dirname in sys.path:
+ candidate = os.path.join(dirname, path)
+ if match(candidate):
+ return candidate
+ raise InfrastructureError("Cannot find file %s" % path)
+
+ def validate(self):
+ if not hasattr(self.job.device, 'config'): # FIXME: new devices only
+ try:
+ # FIXME: need a schema and do this inside the NewDevice with a QemuDevice class? (just for parsing)
+ params = self.job.device.parameters['actions']['boot']
+ arch = self.job.device.parameters['architecture']
+ qemu_binary = self._find(params['command'][arch]['qemu_binary'])
+ self.overrides = params['overrides'] # FIXME: resolve how to allow overrides in the schema
+ self.command = [
+ qemu_binary,
+ "-machine",
+ params['parameters']['machine'],
+ "-hda",
+ self.data['download_action']['file'],
+ ]
+ # these options are lists
+ for net_opt in params['parameters']['net']:
+ self.command.extend(["-net", net_opt])
+ for opt in params['parameters']['qemu_options']:
+ self.command.extend([opt])
+ except (KeyError, TypeError) as exc:
+ raise RuntimeError(exc)
+
+ def run(self, connection, args=None):
+ self._log("Boot command: %s" % ' '.join(self.command))
+ # initialise the first Connection object, a command line shell into the running QEMU.
+ # ShellCommand wraps pexpect.spawn.
+ shell = ShellCommand(' '.join(self.command), self.timeout)
+ if shell.exitstatus:
+ raise JobError("%s command exited %d: %s" % (self.command, shell.exitstatus, shell.readlines()))
+ self._log("started a shell command")
+ # CommandRunner expects a pexpect.spawn connection which is the return value
+ # of target.device.power_on executed by boot in the old dispatcher.
+ #
+ # In the new pipeline, the pexpect.spawn is a ShellCommand and the
+ # connection is a ShellSession. CommandRunner inside the ShellSession
+ # turns the ShellCommand into a runner which the ShellSession uses via ShellSession.run()
+ # to run commands issued *after* the device has booted.
+ # pexpect.spawn is one of the raw_connection objects for a Connection class.
+ shell_connection = ShellSession(self.job.device, shell)
+ self.pipeline.run_actions(shell_connection)
+ return shell_connection
diff --git a/lava_dispatcher/pipeline/actions/deploy/image.py b/lava_dispatcher/pipeline/actions/deploy/image.py
index 68cb8b2..59e9ec6 100644
--- a/lava_dispatcher/pipeline/actions/deploy/image.py
+++ b/lava_dispatcher/pipeline/actions/deploy/image.py
@@ -49,6 +49,7 @@ class DeployImageAction(DeployAction):
self.summary = "deploy image"
def prepare(self):
+ # FIXME: move to validate or into DownloadAction?
# mktemp dir
req = requests.head(self.parameters['image']) # just check the headers, do not download.
if req.status_code != req.codes.ok:
@@ -129,8 +130,12 @@ class DeployImage(Deployment):
which can use instance data.
"""
# FIXME: read the device_types/*.conf and match against the job & support methods
- if device.context.device_config.device_type != 'kvm':
- return False
+ if hasattr(device, 'config'):
+ if device.config.device_type != 'kvm':
+ return False
+ else:
+ if device.parameters['device_type'] != 'kvm':
+ return False
# FIXME: only enable once all deployment strategies in basics.yaml are defined!
# if 'image' not in parameters:
# print parameters
diff --git a/lava_dispatcher/pipeline/actions/deploy/mount.py b/lava_dispatcher/pipeline/actions/deploy/mount.py
index 48db144..9f02fea 100644
--- a/lava_dispatcher/pipeline/actions/deploy/mount.py
+++ b/lava_dispatcher/pipeline/actions/deploy/mount.py
@@ -102,10 +102,15 @@ class LoopCheckAction(DeployAction):
self.data['download_action']['available_loops'] = available_loops
def run(self, connection, args=None):
- args = ['sudo', '/sbin/losetup', '-a'] # sudo allows validate to be used in unit tests
+ if 'available_loops' not in self.data['download_action']:
+ # FIXME: why is this data being cleared? Should we re-check anyway?
+ self.validate()
+ args = ['/sbin/losetup', '-a']
pro = self._run_command(args)
mounted_loops = len(pro.strip().split("\n")) if pro else 0
available_loops = self.data['download_action']['available_loops']
+ # FIXME: we should retry as this can happen and be fixed automatically
+ # when one is unmounted
if mounted_loops >= available_loops:
raise InfrastructureError("Insufficient loopback devices?")
self._log("available loops: %s" % available_loops)
@@ -142,11 +147,11 @@ class LoopMountAction(RetryAction):
# FIXME: figure out why deployment_data isn't available during validation.
lava_test_results_dir = self.parameters['deployment_data']['lava_test_results_dir']
self.data['lava_test_results_dir'] = lava_test_results_dir % self.job.device.parameters['hostname']
+ # FIXME: this should not happen !!
if 'offset' not in self.data['download_action']:
raise RuntimeError("Offset action failed")
self.data[self.name]['mntdir'] = self.job.mkdtemp()
mount_cmd = [
- 'sudo',
'mount',
'-o',
'loop,offset=%s' % self.data['download_action']['offset'],
@@ -190,6 +195,7 @@ class MountAction(DeployAction):
# FIXME: not all mount operations will need these actions
self.internal_pipeline = Pipeline(parent=self, job=self.job)
self.internal_pipeline.add_action(OffsetAction())
+ # FIXME: LoopCheckAction and LoopMountAction should be in only one Action
self.internal_pipeline.add_action(LoopCheckAction())
self.internal_pipeline.add_action(LoopMountAction())
@@ -197,6 +203,7 @@ class MountAction(DeployAction):
if self.internal_pipeline:
connection = self.internal_pipeline.run_actions(connection, args)
else:
+ # FIXME: this is a bug that should not happen (using assert?)
raise RuntimeError("Deployment failed to generate a mount pipeline.")
return connection
@@ -211,7 +218,7 @@ class UnmountAction(RetryAction): # FIXME: contextmanager to ensure umounted on
def run(self, connection, args=None):
self._log("umounting %s" % self.data['loop_mount']['mntdir'])
- self._run_command(['sudo', 'umount', self.data['loop_mount']['mntdir']])
+ self._run_command(['umount', self.data['loop_mount']['mntdir']])
# FIXME: is the rm -rf a separate action or a cleanup of this action?
self._run_command(['rm', '-rf', self.data['loop_mount']['mntdir']])
return connection
diff --git a/lava_dispatcher/pipeline/actions/deploy/overlay.py b/lava_dispatcher/pipeline/actions/deploy/overlay.py
index ce9ab4f..f5cd58a 100644
--- a/lava_dispatcher/pipeline/actions/deploy/overlay.py
+++ b/lava_dispatcher/pipeline/actions/deploy/overlay.py
@@ -46,7 +46,10 @@ class OverlayAction(DeployAction):
will need to insert an instance of this class into the
Deploy pipeline, between mount and umount.
The overlay uses the 'mntdir' set by the MountAction
- in the job data
+ in the job data.
+ This class handles parts of the overlay which are independent
+ of the content of the test definitions themselves. Other
+ overlays are handled by TestDefinitionAction.
"""
# FIXME: remove redundant functions copied in from old code
# FIXME: is this ImageOverlayAction or can it work the same way for all deployments?
@@ -65,29 +68,18 @@ class OverlayAction(DeployAction):
# 755 file permissions
self.xmod = stat.S_IRWXU | stat.S_IXGRP | stat.S_IRGRP | stat.S_IXOTH | stat.S_IROTH
- def _inject_testdef_parameters(self, fout): # FIXME: needs a separate action
- # inject default parameters that were defined in yaml first
- fout.write('###default parameters from yaml###\n')
- if 'params' in self.testdef:
- for def_param_name, def_param_value in self.testdef['params'].items():
- fout.write('%s=\'%s\'\n' % (def_param_name, def_param_value))
- fout.write('######\n')
- # inject the parameters that was set in json
- fout.write('###test parameters from json###\n')
- if self._sw_sources and 'test_params' in self._sw_sources[0] and self._sw_sources[0]['test_params'] != '':
- _test_params_temp = eval(self._sw_sources[0]['test_params'])
- for param_name, param_value in _test_params_temp.items():
- fout.write('%s=\'%s\'\n' % (param_name, param_value))
- fout.write('######\n')
-
def _create_target_install(self, hostdir, targetdir): # FIXME: needs a dedicated Action
+ """
+ Use the 'distro' element of the deployment-data to determine which
+ install helper to add to the overlay.
+ """
with open('%s/install.sh' % hostdir, 'w') as f:
self._inject_testdef_parameters(f)
f.write('set -ex\n')
f.write('cd %s\n' % targetdir)
if self.skip_install != 'deps':
- distro = self.context.client.target_device.deployment_data['distro']
+ distro = self.parameters['deployment_data']['distro']
# generic dependencies - must be named the same across all distros
# supported by the testdef
@@ -108,46 +100,6 @@ class OverlayAction(DeployAction):
for cmd in steps:
f.write('%s\n' % cmd)
- def copy_test(self, hostdir, targetdir): # FIXME: needs a dedicated Action
- """Copy the files needed to run this test to the device.
-
- :param hostdir: The location on the device filesystem to copy too.
- :param targetdir: The location `hostdir` will have when the device
- boots.
- """
- utils.ensure_directory(hostdir)
- with open('%s/testdef.yaml' % hostdir, 'w') as f:
- f.write(yaml.dump(self.testdef))
-
- with open('%s/uuid' % hostdir, 'w') as f:
- f.write(self.uuid)
-
- with open('%s/testdef_metadata' % hostdir, 'w') as f:
- f.write(yaml.safe_dump(self.testdef_metadata))
-
- if self.skip_install != "all":
- if 'install' in self.testdef:
- if self.skip_install != 'repos':
- self._create_repos(hostdir)
- self._create_target_install(hostdir, targetdir)
-
- with open('%s/run.sh' % hostdir, 'w') as f:
- self._inject_testdef_parameters(f)
- f.write('set -e\n')
- f.write('export TESTRUN_ID=%s\n' % self.test_id)
- f.write('cd %s\n' % targetdir)
- f.write('UUID=`cat uuid`\n')
- f.write('echo "<LAVA_SIGNAL_STARTRUN $TESTRUN_ID $UUID>"\n')
- f.write('#wait for an ack from the dispatcher\n')
- f.write('read\n')
- steps = self.testdef['run'].get('steps', [])
- if steps:
- for cmd in steps:
- f.write('%s\n' % cmd)
- f.write('echo "<LAVA_SIGNAL_ENDRUN $TESTRUN_ID $UUID>"\n')
- f.write('#wait for an ack from the dispatcher\n')
- f.write('read\n')
-
def _copy_runner(self, mntdir):
shell = self.parameters['deployment_data']['lava_test_sh_cmd']
@@ -188,10 +140,8 @@ class OverlayAction(DeployAction):
self._copy_runner(lava_path)
# load test definitions is done by TestDefinitionAction, so we're finished
# debug: log the overlay directory contents
- self._run_command(["ls", "-l", lava_path])
- self._run_command(["cat", os.path.join(lava_path, 'lava-test-runner.conf')])
- self._run_command(["ls", "-l", os.path.join(lava_path, 'bin')])
- self._run_command(["ls", "-l", os.path.join(lava_path, 'tests')])
+ # self._run_command(["cat", os.path.join(lava_path, 'lava-test-runner.conf')])
+ # self._run_command(["ls", "-lR", os.path.join(lava_path, 'tests')])
return connection
diff --git a/lava_dispatcher/pipeline/actions/deploy/testdef.py b/lava_dispatcher/pipeline/actions/deploy/testdef.py
index d0e9ef9..16f8d83 100644
--- a/lava_dispatcher/pipeline/actions/deploy/testdef.py
+++ b/lava_dispatcher/pipeline/actions/deploy/testdef.py
@@ -19,9 +19,11 @@
# with this program; if not, see <http://www.gnu.org/licenses>.
import os
+import yaml
import base64
import tarfile
import StringIO
+from uuid import uuid4
from lava_dispatcher.pipeline.action import (
Pipeline,
RetryAction,
@@ -41,6 +43,8 @@ class RepoAction(RetryAction):
self.tmpdir = None
self.vcs_binary = None
self.runner = None
+ self.uuid = str(uuid4())
+ self.testdef = None
def validate(self):
if self.vcs_binary and not os.path.exists(self.vcs_binary):
@@ -53,9 +57,27 @@ class RepoAction(RetryAction):
self.runner = ('%s/tests/%s\n' % (prefix, self.parameters['test_name']))
# mntdir is a temporary directory, not available at validate stage.
self.tmpdir = self.data['mount_action']['mntdir']
+ # NOTE: the eventual runner_path must remain empty until after the VCS clone, so let the VCS clone create the final dir
+
+ # if 'test-case-deps' in testdef: # FIXME - is this needed?
+ # self._get_dependent_test_cases(testdef)
+
+ # install is done from the main overlay
+ # TODO: implement
+ # if self.skip_install != "all":
+ # if 'install' in self.testdef:
+ # if self.skip_install != 'repos':
+ # self._create_repos(hostdir)
+ # self._create_target_install(hostdir, targetdir)
+
return connection
+def indices(string, char):
+
+ return [i for i, c in enumerate(string) if c == char]
+
+
class GitRepoAction(RepoAction):
"""
Each repo action is for a single repository,
@@ -83,7 +105,55 @@ class GitRepoAction(RepoAction):
os.chdir(runner_path)
self._run_command([self.vcs_binary, 'checkout', self.parameters['revision']])
commit_id = self._run_command([self.vcs_binary, 'log', '-1', '--pretty=%H']).strip()
- self.data[self.name]['commit_id'] = commit_id
+
+ # now read the YAML to create a testdef dict to retrieve metadata
+ yaml_file = os.path.join(runner_path, self.parameters['path'])
+ if not os.path.exists(yaml_file):
+ raise JobError("Unable to find test definition YAML: %s" % yaml_file)
+ with open(yaml_file, 'r') as f:
+ self.testdef = yaml.safe_load(f)
+
+ with open("%s/testdef.yaml" % runner_path, 'w') as f:
+ yaml.safe_dump(self.testdef, f)
+
+ # TODO: check if this copy dict is needed or if other routines
+ # can use the fields directly. Needs to be per handler as it reads the YAML & parameters.
+ self.data.update({
+ self.name: {
+ 'os': self.testdef['metadata'].get('os', ''),
+ 'devices': self.testdef['metadata'].get('devices', ''),
+ 'environment': self.testdef['metadata'].get('environment', ''),
+ 'branch_vcs': 'git',
+ 'project_name': self.parameters['test_name'], # FIXME: do we need this duplicate?
+ 'commit_id': commit_id, # FIXME: do we need this?
+ }
+ })
+
+ # write out the UUID of each test definition.
+ with open('%s/uuid' % runner_path, 'w') as f:
+ f.write(self.uuid)
+
+ # FIXME: does this match old-world test-shell?
+ with open('%s/testdef_metadata' % runner_path, 'w') as f:
+ f.write(yaml.safe_dump(self.data[self.name]))
+
+ with open('%s/run.sh' % runner_path, 'w') as f:
+ # self._inject_testdef_parameters(f)
+ f.write('set -ex\n')
+ f.write('export TESTRUN_ID=%s\n' % self.testdef['metadata']['name'])
+ f.write('cd %s\n' % self.runner)
+ f.write('UUID=`cat uuid`\n')
+ f.write('echo "<LAVA_SIGNAL_STARTRUN $TESTRUN_ID $UUID>"\n')
+ f.write('#wait for an ack from the dispatcher\n')
+ f.write('read\n')
+ steps = self.testdef['run'].get('steps', [])
+ if steps:
+ for cmd in steps:
+ f.write('%s\n' % cmd)
+ f.write('echo "<LAVA_SIGNAL_ENDRUN $TESTRUN_ID $UUID>"\n')
+ f.write('#wait for an ack from the dispatcher\n')
+ f.write('read\n')
+
os.chdir(cwd)
if not self.valid:
raise RuntimeError("Unable to get test definition from %s (%s)" % (self.vcs_binary, self.parameters))
@@ -117,6 +187,26 @@ class BzrRepoAction(RepoAction):
])
if self.errors:
raise RuntimeError("Unable to get test definition from %s (%s)" % (self.vcs_binary, self.parameters))
+
+ # now read the YAML to create a testdef dict to retrieve metadata
+ yaml_file = os.path.join(runner_path, self.parameters['path'])
+ if not os.path.exists(yaml_file):
+ raise JobError("Unable to find test definition YAML: %s" % yaml_file)
+ with open(yaml_file, 'r') as f:
+ self.testdef = yaml.safe_load(f)
+
+ # FIXME: do this once and set the branch_vcs per handler?
+ self.data.update({
+ self.name: {
+ 'os': self.testdef['metadata'].get('os', ''),
+ 'devices': self.testdef['metadata'].get('devices', ''),
+ 'environment': self.testdef['metadata'].get('environment', ''),
+ 'branch_vcs': 'bzr',
+ 'project_name': self.parameters['test_name'], # FIXME: do we need this duplicate?
+ 'commit_id': commit_id, # FIXME: do we need this?
+ }
+ })
+
return connection
@@ -189,12 +279,35 @@ class UrlRepoAction(DownloaderAction):
raise JobError('Unable to get test definition from url\n' + str(exc))
finally:
self._log("Downloaded test definition file to %s." % runner_path)
+
+ i = []
+ for e in " $&()\"'<>/\\|;`":
+ i.extend(indices(self.testdef["metadata"]["name"], e))
+ if i:
+ msg = "Test name contains invalid symbol(s) at position(s): %s" % ", ".join(map(str, i))
+ raise JobError(msg)
+
+ try:
+ self.testdef["metadata"]["name"].encode()
+ except UnicodeEncodeError as e:
+ msg = "Test name contains non-ascii symbols: %s" % e
+ raise JobError(msg)
+
return connection
class TestDefinitionAction(TestAction):
def __init__(self):
+ """
+ The TestDefinitionAction installs each test definition into
+ the overlay. It does not execute the scripts in the test
+ definition, that is the job of the TestAction class.
+ One TestDefinitionAction handles all test definitions for
+ the current job.
+ In addition, a TestOverlayAction is added to the pipeline
+ to handle parts of the overlay which are test definition dependent.
+ """
super(TestDefinitionAction, self).__init__()
self.name = "test-definition"
self.description = "load test definitions into image"
@@ -219,12 +332,14 @@ class TestDefinitionAction(TestAction):
else:
self.errors = "unsupported handler"
raise JobError("unsupported testdef handler: %s %s" % (testdef, testdef['from']))
+ # set the full set of job YAML parameters for this handler as handler parameters.
handler.parameters = testdef
# store the correct test_name before incrementing the local index dict
handler.parameters['test_name'] = "%s_%s" % (len(index.keys()), handler.parameters['name'])
index[len(index.keys())] = handler.parameters['name']
self.internal_pipeline.add_action(handler)
# FIXME: the outer pipeline may add unwanted data to the parameters['test']
+ self.internal_pipeline.add_action(TestOverlayAction())
def validate(self):
if not self.job:
@@ -247,7 +362,46 @@ class TestDefinitionAction(TestAction):
self._log("Validation failed")
raise JobError("Invalid job data: %s\n" % '\n'.join(self.errors))
+ def _inject_testdef_parameters(self, fout): # FIXME: needs a separate action
+ # inject default parameters that were defined in yaml first
+ fout.write('###default parameters from yaml###\n')
+ if 'params' in self.testdef:
+ for def_param_name, def_param_value in self.testdef['params'].items():
+ fout.write('%s=\'%s\'\n' % (def_param_name, def_param_value))
+ fout.write('######\n')
+ # inject the parameters that was set in json
+ fout.write('###test parameters from json###\n')
+ if self._sw_sources and 'test_params' in self._sw_sources[0] and self._sw_sources[0]['test_params'] != '':
+ _test_params_temp = eval(self._sw_sources[0]['test_params'])
+ for param_name, param_value in _test_params_temp.items():
+ fout.write('%s=\'%s\'\n' % (param_name, param_value))
+ fout.write('######\n')
+
+ def copy_test(self, hostdir, targetdir): # FIXME: needs porting to the new classes
+ """Copy the files needed to run this test to the device.
+
+ :param hostdir: The location on the device filesystem to copy too.
+ :param targetdir: The location `hostdir` will have when the device
+ boots.
+ """
+
+ with open('%s/testdef_metadata' % hostdir, 'w') as f:
+ f.write(yaml.safe_dump(self.testdef_metadata))
+
+ if self.skip_install != "all":
+ if 'install' in self.testdef:
+ if self.skip_install != 'repos':
+ self._create_repos(hostdir)
+ self._create_target_install(hostdir, targetdir)
+
def run(self, connection, args=None):
+ """
+ Puts the requested test definition files into the overlay
+
+ :param connection: Connection object, if any.
+ :param args: Not used.
+ :return: the received Connection.
+ """
self._log("Loading test definitions")
# developer hack - if the image hasn't been downloaded this time, it may already contain old files
# should really be an rmtree but it is only here to save developer time on downloads...
@@ -256,5 +410,31 @@ class TestDefinitionAction(TestAction):
connection = self.internal_pipeline.run_actions(connection)
with open('%s/lava-test-runner.conf' % self.data['mount_action']['mntdir'], 'a') as runner_conf:
for handler in self.internal_pipeline.actions:
- runner_conf.write(handler.runner)
+ if isinstance(handler, RepoAction) or isinstance(handler, UrlRepoAction):
+ runner_conf.write(handler.runner)
+ if isinstance(handler, TestAction): # FIXME: separate actions for copy & inject
+ # run copy_test
+ hostdir = self.data['mount_action']['mntdir']
+ targetdir = ''
+ return connection
+
+
+class TestOverlayAction(TestAction):
+
+ def __init__(self):
+ """
+ When a job requires a TestAction, some files need to be added to
+ the existing Overlay as part of Test.
+ This class adds the necessary scripts to support test definitions
+ but which are test definition dependent, like the install handler.
+ """
+ super(TestOverlayAction, self).__init__()
+ self.name = "test-overlay"
+ self.description = "overlay test support files onto image"
+ self.summary = "applying LAVA test overlay"
+
+ def validate(self):
+ pass
+
+ def run(self, connection, args=None):
return connection
diff --git a/lava_dispatcher/pipeline/actions/test/__init__.py b/lava_dispatcher/pipeline/actions/test/__init__.py
index af2435d..1d53ee9 100644
--- a/lava_dispatcher/pipeline/actions/test/__init__.py
+++ b/lava_dispatcher/pipeline/actions/test/__init__.py
@@ -35,5 +35,23 @@ class TestAction(Action):
self.errors = "Repository missing from test definition"
def run(self, connection, args=None):
- self._log("Loading test definitions")
+ """
+ Needs internal actions defined, depending on the job
+ setup SignalDirector
+ Add MultiNodeSignalDirector, if required
+ Add LMPSignalDirector, if required
+ work out how to do _keep_running with separate classes for multinode & lmp
+ """
+ if not connection:
+ self._log("No connection!")
+ self._log("Executing test definitions using %s" % connection.name)
+ # internal actions:
+ # setup SignalDirector
+ # set proxy
+ # connection.run_command("ls -r %s" % self.data['lava_test_results_dir'])
+ connection.run_command(
+ "%s/bin/lava-test-runner %s" % (
+ self.data['lava_test_results_dir'],
+ self.data['lava_test_results_dir']),
+ )
return connection
diff --git a/lava_dispatcher/pipeline/device.py b/lava_dispatcher/pipeline/device.py
index 2a3c732..231084b 100644
--- a/lava_dispatcher/pipeline/device.py
+++ b/lava_dispatcher/pipeline/device.py
@@ -45,6 +45,32 @@ class DeviceTypeParser(object):
return data
+class NewDeviceDefaults(object):
+ """
+ Placeholder for an eventual schema based on the current device config schema
+ but adapted to the new device parameter structure.
+ Ideally, use an external file as the schema
+ """
+
+ # TODO! this should be a YAML file on the filesystem
+ def __init__(self):
+ test_image_prompts = [r"\(initramfs\)", # check if the r prefix breaks matching later & remove \.
+ "linaro-test",
+ "/ #",
+ "root@android",
+ "root@linaro",
+ "root@master",
+ "root@debian",
+ "root@linaro-nano:~#",
+ "root@linaro-developer:~#",
+ "root@linaro-server:~#",
+ "root@genericarmv7a:~#",
+ "root@genericarmv8:~#"]
+ self.parameters = {
+ 'test_image_prompts': test_image_prompts
+ }
+
+
class NewDevice(object):
# FIXME: replace the current Device class with this one.
@@ -59,15 +85,18 @@ class NewDevice(object):
if not os.path.exists(os.path.join(default_config_path, 'devices', "%s.conf" % target)):
raise RuntimeError("Unable to use new devices: %s" % default_config_path)
+ defaults = NewDeviceDefaults()
# parameters dict will update if new settings are found, so repeat for customisation files when those exist
- self.parameters = dev_parser.parse(open(os.path.join(default_config_path, 'devices', "%s.conf" % target)))
- self.parameters = dev_parser.parse(open(os.path.join(default_config_path, 'device_types', "%s.conf" % self.parameters['device_type'])))
- self.parameters['hostname'] = target # FIXME: is this a valid assumption?
+ self.__parameters__.update(defaults.parameters)
+ self.__parameters__.update(dev_parser.parse(open(os.path.join(default_config_path, 'devices', "%s.conf" % target))))
+ self.__parameters__.update(dev_parser.parse(open(os.path.join(default_config_path, 'device_types', "%s.conf" % self.parameters['device_type']))))
+ self.__parameters__['hostname'] = target # FIXME: is this a valid assumption?
@property
def parameters(self):
return self.__parameters__
+ # FIXME: why having one function for that?
def __set_parameters__(self, data):
self.__parameters__.update(data)
@@ -80,4 +109,5 @@ class NewDevice(object):
Validates the combination of the job and the device
*before* the Deployment actions are initialised.
"""
+ # FIXME: shoudl be raise NotImplementedError
pass
diff --git a/lava_dispatcher/pipeline/device_types/kvm.conf b/lava_dispatcher/pipeline/device_types/kvm.conf
index c120e64..391020e 100644
--- a/lava_dispatcher/pipeline/device_types/kvm.conf
+++ b/lava_dispatcher/pipeline/device_types/kvm.conf
@@ -14,19 +14,20 @@ actions:
# Action specific stanza
command:
# allows for the one type to support different binaries
- - amd64:
- - qemu_binary: qemu-system-x86_64
+ amd64:
+ qemu_binary: qemu-system-x86_64
# only overrides can be overridden in the Job
- overrides:
+ overrides:
- boot_cmds
- qemu_options
parameters:
- - boot_cmds:
+ boot_cmds:
- root: /dev/sda1
- console: ttyS0,115200
- - qemu_options:
- - nographic
- machine: accel=kvm:tcg
- net:
+ qemu_options:
+ - -nographic
+ machine:
+ accel=kvm:tcg
+ net:
- nic,model=virtio
- user
diff --git a/lava_dispatcher/pipeline/devices/kvm01.conf b/lava_dispatcher/pipeline/devices/kvm01.conf
index 07ba553..fa50bf0 100644
--- a/lava_dispatcher/pipeline/devices/kvm01.conf
+++ b/lava_dispatcher/pipeline/devices/kvm01.conf
@@ -3,3 +3,5 @@
device_type: kvm
root_part: 1
+architecture: amd64
+memory: 512
diff --git a/lava_dispatcher/pipeline/job.py b/lava_dispatcher/pipeline/job.py
index 9d3aea0..1333378 100644
--- a/lava_dispatcher/pipeline/job.py
+++ b/lava_dispatcher/pipeline/job.py
@@ -49,6 +49,7 @@ class Job(object):
self.pipeline = None
self.actions = None
self._scratch_dir = None
+ self.connection = None
def set_pipeline(self, pipeline):
self.pipeline = pipeline
@@ -58,6 +59,7 @@ class Job(object):
def context(self):
return self.__context__
+ # FIXME: remove this function
def __set_context__(self, data):
self.__context__ = data
@@ -74,9 +76,12 @@ class Job(object):
structure['job'] = {
'parameters': self.parameters
}
+ # FIXME: output the deployment data here and remove from the Actions
structure.update(self.pipeline.describe())
return structure
+ # FIXME: what about having one base class for all the classes that have
+ # (prepare, validate, run, cleanup)?
def validate(self, simulate=False):
"""
Needs to validate the parameters
@@ -91,8 +96,7 @@ class Job(object):
self.pipeline.validate_actions()
def run(self):
- self.pipeline.validate_actions()
- self.pipeline.run_actions(None)
+ self.pipeline.run_actions(self.connection) # FIXME: some Deployment methods may need to set a Connection.
# FIXME how to get rootfs with multiple deployments, and at arbitrary
# points in the pipeline?
# rootfs = None
@@ -105,10 +109,12 @@ class Job(object):
# results_dir = None
# self.action.post_process(results_dir)
+ # FIXME: should be moved to a specific helper module
def rmtree(self, directory):
# FIXME: change to self._run_command
subprocess.call(['rm', '-rf', directory])
+ # FIXME: should be moved to a specific helper module
def mkdtemp(self, basedir='/tmp'):
"""
returns a temporary directory that's deleted when the process exits
diff --git a/lava_dispatcher/pipeline/parser.py b/lava_dispatcher/pipeline/parser.py
index d0d3242..dbcc009 100644
--- a/lava_dispatcher/pipeline/parser.py
+++ b/lava_dispatcher/pipeline/parser.py
@@ -26,11 +26,15 @@ from lava_dispatcher.pipeline.action import (
Pipeline,
Action,
Deployment,
+ Boot,
+ FinalizeAction,
+ LavaTest,
JobError
)
from lava_dispatcher import deployment_data
# needed for the Deployment select call, despite what pylint thinks.
-from lava_dispatcher.pipeline.actions.deploy.image import DeployImage
+from lava_dispatcher.pipeline.actions.deploy.image import DeployImage # pylint: disable=unused-import
+from lava_dispatcher.pipeline.actions.boot.kvm import BootKVM # pylint: disable=unused-import
class JobParser(object):
@@ -84,10 +88,18 @@ class JobParser(object):
deploy.action.yaml_line = line
device.deployment_data = deployment_data.get(deploy.action.parameters['os'])
deploy.action.parameters = {'deployment_data': device.deployment_data}
+ elif name == "boot":
+ boot = Boot.select(device, action_data[name])(pipeline)
+ boot.action.parameters = action_data[name]
+ boot.action.yaml_line = line
+# elif name == "test":
+# lavatest = LavaTest.select(device, action_data[name])(pipeline)
+# lavatest.action.parameters = action_data[name]
+# lavatest.action.yaml_line = line
else:
- action_class = Action.find(name)
+ # May only end up being used for submit as other actions all need strategy method objects
# select the specific action of this class for this job
- action = action_class()
+ action = Action.find(name)()
# put parameters (like rootfs_type, results_dir) into the actions.
if type(action_data[name]) == dict:
action.parameters = action_data[name]
@@ -102,6 +114,8 @@ class JobParser(object):
# uncomment for debug
# print action.parameters
+ # there's always going to need to be a finalize_process action
+ pipeline.add_action(FinalizeAction())
# the only parameters sent to the job are job parameters
# like job_name, logging_level or target_group.
data.pop('actions')
diff --git a/lava_dispatcher/pipeline/serial.py b/lava_dispatcher/pipeline/serial.py
index 25fcaa5..0708cc9 100644
--- a/lava_dispatcher/pipeline/serial.py
+++ b/lava_dispatcher/pipeline/serial.py
@@ -1,9 +1,40 @@
-from lava_dispatcher.pipeline import *
-from lava_dispatcher.utils import logging_spawn
+# Copyright (C) 2014 Linaro Limited
+#
+# Author: Neil Williams <neil.williams@linaro.org>
+#
+# This file is part of LAVA Dispatcher.
+#
+# LAVA Dispatcher is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# LAVA Dispatcher is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along
+# with this program; if not, see <http://www.gnu.org/licenses>.
+
+from lava_dispatcher.pipeline import Action, Connection, Timeout
+from lava_dispatcher.pipeline.shell import ShellCommand
class ConnectToSerial(Action):
+ def __init__(self):
+ super(ConnectToSerial, self).__init__()
+ self.name = "connect-to-serial"
+ self.description = "connect to the serial port of the device"
+ self.summary = "connecting to serial"
+ self.timeout = Timeout(self.name)
+
+ def validate(self):
+ if 'connection_command' not in self.job.device.parameters:
+ raise RuntimeError("%s does not have a connection_command parameter" % self.job.device.parameters['hostname'])
+
def run(self, connection, args=None):
- telnet = spawn_command(self.device.config.connection_command)
- return Connection(self.device, telnet)
+ telnet = ShellCommand(self.job.device.parameters['connection_command'], self.timeout)
+ return Connection(self.job.device, telnet)
diff --git a/lava_dispatcher/pipeline/shell.py b/lava_dispatcher/pipeline/shell.py
index da6ee9d..438f8f0 100644
--- a/lava_dispatcher/pipeline/shell.py
+++ b/lava_dispatcher/pipeline/shell.py
@@ -1,21 +1,137 @@
-from lava_dispatcher.pipeline.action import Connection, Action
+# Copyright (C) 2014 Linaro Limited
+#
+# Author: Neil Williams <neil.williams@linaro.org>
+#
+# This file is part of LAVA Dispatcher.
+#
+# LAVA Dispatcher is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# LAVA Dispatcher is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along
+# with this program; if not, see <http://www.gnu.org/licenses>.
+
+import os
+import sys
+import time
+import logging
+import pexpect
+from lava_dispatcher.pipeline.action import Connection, Action, JobError
from lava_dispatcher.client.base import CommandRunner
+class ShellCommand(pexpect.spawn): # pylint: disable=too-many-public-methods
+ """
+ Run a command over a connection using pexpect instead of
+ subprocess, i.e. not on the dispatcher itself.
+ Takes a Timeout object (to support overrides and logging)
+
+ A ShellCommand is a raw_connection for a ShellConnection instance.
+ """
+
+ def __init__(self, command, lava_timeout, cwd=None):
+ pexpect.spawn.__init__(
+ self, command, timeout=lava_timeout.duration, cwd=cwd, logfile=sys.stdout)
+ self.name = "ShellCommand"
+ # serial can be slow, races do funny things, so increase delay
+ # FIXME: this as to be a constant, written somewhere with all constants
+ self.delaybeforesend = 0.05
+ self.lava_timeout = lava_timeout
+ yaml_log = logging.getLogger("YAML")
+ yaml_log.debug({'spawn': {
+ lava_timeout.name: lava_timeout.duration,
+ 'command': self.command
+ }})
+ # FIXME: consider a logginghandler as with standard actions or use the handler of the calling Action?
+
+ def sendline(self, s='', delay=0, send_char=True): # pylint: disable=arguments-differ
+ """
+ Extends pexpect.sendline so that it can support the delay argument which allows a delay
+ between sending each character to get around slow serial problems (iPXE).
+ pexpect sendline does exactly the same thing: calls send for the string then os.linesep.
+
+ :param s: string to send
+ :param delay: delay in milliseconds between sending each character
+ :param send_char: send one character or entire string
+ """
+ self.send(s, delay, send_char)
+ self.send(os.linesep, delay)
+
+ def sendcontrol(self, char):
+ # FIXME: the getLogger should be done only once
+ yaml_log = logging.getLogger("YAML")
+ yaml_log.debug("sending control character: %s", char)
+ return super(ShellCommand, self).sendcontrol(char)
+
+ def send(self, string, delay=0, send_char=True): # pylint: disable=arguments-differ
+ """
+ Extends pexpect.send to support extra arguments, delay and send by character flags.
+ """
+ # FIXME: the getLogger should be done only once
+ yaml_log = logging.getLogger("YAML")
+ yaml_log.debug("send (delay_ms=%s): %s ", delay, string)
+ sent = 0
+ delay = float(delay) / 1000
+ if send_char:
+ for char in string:
+ sent += super(ShellCommand, self).send(char)
+ time.sleep(delay)
+ else:
+ sent = super(ShellCommand, self).send(string)
+ return sent
+
+ def expect(self, *args, **kw):
+ # FIXME: the getLogger should be done only once
+ yaml_log = logging.getLogger("YAML")
+ std_log = logging.getLogger("ASCII")
+
+ # FIXME: this produces the most ugly log output of any part of the dispatcher.
+ if len(args) == 1:
+ yaml_log.debug("expect (%d): '%s'", self.lava_timeout.duration, args[0])
+ else:
+ yaml_log.debug("expect (%d): '%s'", self.lava_timeout.duration, str(args))
+
+ try:
+ proc = super(ShellCommand, self).expect(*args, **kw)
+ except pexpect.TIMEOUT:
+ raise JobError("command timed out.")
+ except pexpect.EOF:
+ raise RuntimeError(" ".join(self.before.split('\r\n')))
+ yaml_log.debug("Prompt matched.")
+ return proc
+
+ def empty_buffer(self):
+ """Make sure there is nothing in the pexpect buffer."""
+ index = 0
+ while index == 0:
+ index = self.expect(['.+', pexpect.EOF, pexpect.TIMEOUT], timeout=1)
+
+
class ShellSession(Connection):
- def __init__(self, device, raw_connection):
- super(ShellSession, self).__init__(device, raw_connection)
+ def __init__(self, device, shell_command):
+ super(ShellSession, self).__init__(device, shell_command)
self.__runner__ = None
+ self.name = "ShellSession"
@property
def runner(self):
if self.__runner__ is None:
device = self.device
- connection = self.raw_connection
- prompt_str = device.config.test_image_prompts
- prompt_str_includes_rc = device.config.tester_ps1_includes_rc
- self.__runner__ = CommandRunner(connection, prompt_str,
+ spawned_shell = self.raw_connection # ShellCommand(pexpect.spawn)
+ prompt_str = device.parameters['test_image_prompts']
+ prompt_str_includes_rc = True # FIXME
+# prompt_str_includes_rc = device.config.tester_ps1_includes_rc
+ # FIXME: although CommandRunner can be used, NetworkRunner and others need to be rewritten for logging & timeout support.
+ # The Connection for a CommandRunner in the pipeline needs to be a ShellCommand, not logging_spawn
+ self.__runner__ = CommandRunner(spawned_shell, prompt_str,
prompt_str_includes_rc)
return self.__runner__
@@ -23,16 +139,24 @@ class ShellSession(Connection):
self.runner.run(command)
def wait(self):
+ yaml_log = logging.getLogger("YAML")
+ yaml_log.debug("sending new line. Waiting for prompt")
self.raw_connection.sendline("")
self.runner.wait_for_prompt()
class ExpectShellSession(Action):
+ """
+ Waits for a shell connection to the device for the current job.
+ """
def __init__(self):
super(ExpectShellSession, self).__init__()
+ self.name = "expect-shell-connection"
+ self.summary = "Expect a shell prompt"
+ self.description = "Wait for a shell"
def run(self, connection, args=None):
- shell = ShellSession(connection.device, connection.raw_connection)
- shell.wait()
- return shell
+ self._log("Waiting for prompt")
+ connection.wait()
+ return connection
diff --git a/lava_dispatcher/pipeline/test/sample_jobs/basics.yaml b/lava_dispatcher/pipeline/test/sample_jobs/basics.yaml
index 8bef863..2214a25 100644
--- a/lava_dispatcher/pipeline/test/sample_jobs/basics.yaml
+++ b/lava_dispatcher/pipeline/test/sample_jobs/basics.yaml
@@ -1,4 +1,4 @@
-# Sample JOB defitinition for LAVA dispatcher
+# Sample JOB definition for LAVA dispatcher
device_type: whatever
diff --git a/lava_dispatcher/pipeline/test/sample_jobs/kvm.yaml b/lava_dispatcher/pipeline/test/sample_jobs/kvm.yaml
index fea88a9..b7752bf 100644
--- a/lava_dispatcher/pipeline/test/sample_jobs/kvm.yaml
+++ b/lava_dispatcher/pipeline/test/sample_jobs/kvm.yaml
@@ -1,4 +1,4 @@
-# Sample JOB defitinition for a KVM
+# Sample JOB definition for a KVM
device_type: kvm
diff --git a/lava_dispatcher/pipeline/test/test_basic.py b/lava_dispatcher/pipeline/test/test_basic.py
index debd163..8d8b83d 100644
--- a/lava_dispatcher/pipeline/test/test_basic.py
+++ b/lava_dispatcher/pipeline/test/test_basic.py
@@ -20,6 +20,7 @@
import sys
import os
+import time
from StringIO import StringIO
import unittest
import yaml
@@ -180,6 +181,7 @@ class TestPipeline(unittest.TestCase):
self.name = "fake-action"
def run(self, connection, args=None):
+ time.sleep(1)
self.ran = True
def test_create_empty_pipeline(self):
diff --git a/lava_dispatcher/pipeline/test/test_defs.py b/lava_dispatcher/pipeline/test/test_defs.py
index fc5ab9a..f468855 100644
--- a/lava_dispatcher/pipeline/test/test_defs.py
+++ b/lava_dispatcher/pipeline/test/test_defs.py
@@ -21,7 +21,11 @@
from lava_dispatcher.pipeline.test.test_basic import Factory
from lava_dispatcher.tests.helper import LavaDispatcherTestCase
from lava_dispatcher.pipeline.actions.deploy import DeployAction
-from lava_dispatcher.pipeline.actions.deploy.testdef import TestDefinitionAction, GitRepoAction
+from lava_dispatcher.pipeline.actions.deploy.testdef import (
+ TestDefinitionAction,
+ GitRepoAction,
+ TestOverlayAction
+)
# Test the loading of test definitions within the deploy stage
@@ -39,12 +43,14 @@ class TestDefinitionHandlers(LavaDispatcherTestCase):
self.assertIsNotNone(action.name)
if isinstance(action, DeployAction):
testdef = action.pipeline.children[action.pipeline][4]
- self.assertEqual(len(testdef.internal_pipeline.actions), 2)
+ self.assertEqual(len(testdef.internal_pipeline.actions), 3)
self.assertIsInstance(testdef, TestDefinitionAction)
testdef.validate()
self.assertTrue(testdef.valid)
for repo_action in testdef.internal_pipeline.actions:
- self.assertIsInstance(repo_action, GitRepoAction)
+ if not isinstance(repo_action, GitRepoAction) and not\
+ isinstance(repo_action, TestOverlayAction):
+ self.fail("%s does not match GitRepoAction or TestOverlayAction" % type(repo_action))
repo_action.validate()
self.assertTrue(repo_action.valid)
# FIXME: needs deployment_data to be visible during validation
diff --git a/lava_dispatcher/pipeline/test/test_job.py b/lava_dispatcher/pipeline/test/test_job.py
index 6eb7b06..f461f00 100644
--- a/lava_dispatcher/pipeline/test/test_job.py
+++ b/lava_dispatcher/pipeline/test/test_job.py
@@ -37,6 +37,7 @@ from lava_dispatcher.pipeline.actions.deploy.mount import (
)
from lava_dispatcher.pipeline.actions.deploy.overlay import OverlayAction, CustomisationAction
from lava_dispatcher.pipeline.actions.deploy.testdef import TestDefinitionAction
+from lava_dispatcher.pipeline.actions.boot.kvm import BootAction
class TestBasicJob(LavaDispatcherTestCase):
@@ -158,7 +159,7 @@ class TestKVMBasicDeploy(LavaDispatcherTestCase):
overlay = None
unmount = None
self.assertTrue(os.path.exists(self.job.parameters['output_dir']))
- self.assertEqual(len(self.job.pipeline.describe().values()), 16)
+ self.assertEqual(len(self.job.pipeline.describe().values()), 19) # this will keep changing until KVM is complete.
for action in self.job.pipeline.actions:
if isinstance(action, DeployAction):
# check parser has created a suitable deployment
@@ -277,7 +278,7 @@ class TestKVMBasicDeploy(LavaDispatcherTestCase):
def test_kvm_basic_boot(self):
for action in self.job.pipeline.actions:
- if action.name == 'boot':
+ if isinstance(action, BootAction):
# get the action & populate it
self.assertEqual(action.parameters['method'], 'kvm')
diff --git a/lava_dispatcher/utils.py b/lava_dispatcher/utils.py
index 7b4816f..185a54a 100644
--- a/lava_dispatcher/utils.py
+++ b/lava_dispatcher/utils.py
@@ -190,6 +190,55 @@ def create_ramdisk(ramdisk_dir, tmpdir):
return os.path.join(tmpdir, 'ramdisk.cpio.gz')
+def is_uimage(kernel, context):
+ uimage = ['u-boot', 'uImage']
+
+ # Detect if zImage or uImage is used.
+ cmd = 'file ' + kernel
+ output = context.run_command_get_output(cmd)
+ if any(x in output for x in uimage):
+ return True
+ else:
+ return False
+
+
+def create_uimage(kernel, load_addr, tmp_dir, xip, arch='arm'):
+ load_addr = int(load_addr, 16)
+ uimage_path = '%s/uImage' % tmp_dir
+ if xip:
+ entry_addr = load_addr + 64
+ else:
+ entry_addr = load_addr
+ cmd = 'mkimage -A %s -O linux -T kernel \
+ -C none -a 0x%x -e 0x%x \
+ -d %s %s' % (arch, load_addr,
+ entry_addr, kernel,
+ uimage_path)
+
+ logging.info('Creating uImage')
+ logging.debug(cmd)
+ r = subprocess.call(cmd, shell=True)
+
+ if r == 0:
+ return uimage_path
+ else:
+ raise CriticalError("uImage creation failed")
+
+
+def append_dtb(kernel, dtb, tmp_dir):
+ uimage_path = '%s/kernel-dtb' % tmp_dir
+ cmd = 'cat %s %s > %s' % (kernel, dtb, uimage_path)
+
+ logging.info('Appending dtb to kernel image')
+ logging.debug(cmd)
+ r = subprocess.call(cmd, shell=True)
+
+ if r == 0:
+ return uimage_path
+ else:
+ raise CriticalError("Appending dtb to kernel image failed")
+
+
def ensure_directory(path):
""" ensures the path exists, if it doesn't it will be created
"""