[autotest] Add more build option in autotest create_job tab for FAFT
Add an Advanced Build Options panel for user to specify:
firmware build (RW), firmware RO build, and test source build.
Then create a suite job from AFE to update both CrOS and firmware.
BUG=chromium:493429
TEST=local test
http://dshi.mtv/afe/#tab_id=create_job
1. check AFE shows the Advanced Build Options panel
2. Confirm the builds specified in the options are used in the sutie job run.
3. Confirm non-suite job can't be created with firmware image specified.
sample cros build: veyron_jerry-release/R45-7201.0.0
sample firmware build: veyron_jerry-firmware/R41-6588.106.0
DEPLOY=afe,apache
Change-Id: I81e1f5f81aaa9dfb5fe7b9f2f3677b8fb437130c
Reviewed-on: https://chromium-review.googlesource.com/281021
Trybot-Ready: Dan Shi <dshi@chromium.org>
Tested-by: Dan Shi <dshi@chromium.org>
Reviewed-by: Simran Basi <sbasi@chromium.org>
Commit-Queue: Dan Shi <dshi@chromium.org>
diff --git a/frontend/afe/rpc_interface.py b/frontend/afe/rpc_interface.py
index 64e8ca7..1a19802 100644
--- a/frontend/afe/rpc_interface.py
+++ b/frontend/afe/rpc_interface.py
@@ -45,6 +45,7 @@
from autotest_lib.frontend.tko import rpc_interface as tko_rpc_interface
from autotest_lib.server import frontend
from autotest_lib.server import utils
+from autotest_lib.server.cros import provision
from autotest_lib.server.cros.dynamic_suite import tools
from autotest_lib.site_utils import status_history
@@ -779,7 +780,9 @@
def create_job_page_handler(name, priority, control_file, control_type,
- image=None, hostless=False, **kwargs):
+ image=None, hostless=False, firmware_rw_build=None,
+ firmware_ro_build=None, test_source_build=None,
+ **kwargs):
"""\
Create and enqueue a job.
@@ -787,6 +790,13 @@
@param priority Integer priority of this job. Higher is more important.
@param control_file String contents of the control file.
@param control_type Type of control file, Client or Server.
+ @param image: ChromeOS build to be installed in the dut. Default to None.
+ @param firmware_rw_build: Firmware build to update RW firmware. Default to
+ None, i.e., RW firmware will not be updated.
+ @param firmware_ro_build: Firmware build to update RO firmware. Default to
+ None, i.e., RO firmware will not be updated.
+ @param test_source_build: Build to be used to retrieve test code. Default
+ to None.
@param kwargs extra args that will be required by create_suite_job or
create_job.
@@ -798,9 +808,15 @@
'control_file' : "Control file cannot be empty"})
if image and hostless:
+ builds = {}
+ builds[provision.CROS_VERSION_PREFIX] = image
+ if firmware_rw_build:
+ builds[provision.FW_VERSION_PREFIX] = firmware_rw_build
+ if firmware_ro_build:
+ builds[provision.FW_RO_VERSION_PREFIX] = firmware_ro_build
return site_rpc_interface.create_suite_job(
name=name, control_file=control_file, priority=priority,
- build=image, **kwargs)
+ builds=builds, test_source_build=test_source_build, **kwargs)
return create_job(name, priority, control_file, control_type, image=image,
hostless=hostless, **kwargs)
@@ -886,6 +902,8 @@
test_parameter=image_parameter, parameter_value=image,
parameter_type='string')
+ # TODO(crbug.com/502638): save firmware build etc to parameterized_job.
+
# By passing a parameterized_job to create_job_common the job entry in
# the afe_jobs table will have the field parameterized_job_id set.
# The scheduler uses this id in the afe_parameterized_jobs table to
diff --git a/frontend/afe/site_rpc_interface.py b/frontend/afe/site_rpc_interface.py
index beb69f9..1daab8f 100644
--- a/frontend/afe/site_rpc_interface.py
+++ b/frontend/afe/site_rpc_interface.py
@@ -212,7 +212,7 @@
max_runtime_mins = max_runtime_mins or timeout * 60
if not board:
- board = utils.ParseBuildName(build)[0]
+ board = utils.ParseBuildName(builds[provision.CROS_VERSION_PREFIX])[0]
# TODO(dshi): crbug.com/496782 Remove argument build and its reference after
# R45 falls out of stable channel.
diff --git a/frontend/client/src/autotest/afe/create/CreateJobViewDisplay.java b/frontend/client/src/autotest/afe/create/CreateJobViewDisplay.java
index 881bde1..add5097 100644
--- a/frontend/client/src/autotest/afe/create/CreateJobViewDisplay.java
+++ b/frontend/client/src/autotest/afe/create/CreateJobViewDisplay.java
@@ -127,6 +127,23 @@
"?",
"Example: \"device_addrs=00:1F:20:33:6A:1E, arg2=value2, arg3=value3\". " +
"Separate multiple args with commas.");
+ private TextBoxImpl firmwareRWBuild = new TextBoxImpl();
+ private ToolTip firmwareRWBuildToolTip = new ToolTip(
+ "?",
+ "Name of the firmware build to update RW firmware of the DUT. Example: " +
+ "\"x86-alex-firmware/R41-6588.9.0\". If no firmware build is specified, " +
+ "the RW firmware of the DUT will not be updated.");
+ private TextBoxImpl firmwareROBuild = new TextBoxImpl();
+ private ToolTip firmwareROBuildToolTip = new ToolTip(
+ "?",
+ "Name of the firmware build to update RO firmware of the DUT. Example: " +
+ "\"x86-alex-firmware/R41-6588.9.0\". If no firmware RO build is specified, " +
+ "the RO firmware of the DUT will not be updated.");
+ private ExtendedListBox testSourceBuildList = new ExtendedListBox();
+ private ToolTip testSourceBuildListToolTip = new ToolTip(
+ "?",
+ "The image/build from which the tests will be fetched and ran from. It can " +
+ "be one of the specified Build Image, Firmware RW Build or the Firmware RO Build.");
private TestSelectorDisplay testSelector = new TestSelectorDisplay();
private CheckBoxPanelDisplay profilersPanel = new CheckBoxPanelDisplay(CHECKBOX_PANEL_COLUMNS);
private CheckBoxImpl runNonProfiledIteration =
@@ -143,6 +160,7 @@
private Button resetButton = new Button("Reset");
private Label viewLink = new Label("");
private DisclosurePanel advancedOptionsPanel = new DisclosurePanel("");
+ private DisclosurePanel firmwareBuildOptionsPanel = new DisclosurePanel("");
public void initialize(HTMLPanel panel) {
jobName.addStyleName("jobname-image-boundedwidth");
@@ -290,16 +308,48 @@
}
}
-
advancedOptionsLayout.setWidth("100%");
advancedOptionsPanel.addStyleName("panel-boundedwidth");
advancedOptionsPanel.add(advancedOptionsLayout);
+ // Setup the Firmware Build options panel
+ firmwareBuildOptionsPanel.getHeaderTextAccessor().setText("Firmware Build Options (optional)");
+ FlexTable firmwareBuildOptionsLayout = new FlexTable();
+
+ firmwareBuildOptionsLayout.getFlexCellFormatter().setColSpan(0, 0, 2);
+ firmwareBuildOptionsLayout.setWidget(0, 0, new Label("Image URL/Build must be specified for " +
+ "updating the firmware of the test device with given firmware build. A servo may be " +
+ "required to be attached to the test device in order to have firmware updated."));
+
+ Panel firmwareRWBuildPanel = new HorizontalPanel();
+ firmwareRWBuild.addStyleName("jobname-image-boundedwidth");
+ firmwareRWBuildPanel.add(firmwareRWBuild);
+ firmwareRWBuildPanel.add(firmwareRWBuildToolTip);
+ firmwareBuildOptionsLayout.setWidget(1, 0, new Label("Firmware RW build:"));
+ firmwareBuildOptionsLayout.setWidget(1, 1, firmwareRWBuildPanel);
+
+ Panel firmwareROBuildPanel = new HorizontalPanel();
+ firmwareROBuild.addStyleName("jobname-image-boundedwidth");
+ firmwareROBuildPanel.add(firmwareROBuild);
+ firmwareROBuildPanel.add(firmwareROBuildToolTip);
+ firmwareBuildOptionsLayout.setWidget(2, 0, new Label("Firmware RO build:"));
+ firmwareBuildOptionsLayout.setWidget(2, 1, firmwareROBuildPanel);
+
+ firmwareBuildOptionsLayout.setWidth("100%");
+ firmwareBuildOptionsPanel.addStyleName("panel-boundedwidth");
+ firmwareBuildOptionsPanel.add(firmwareBuildOptionsLayout);
+ firmwareRWBuild.setEnabled(false);
+ firmwareROBuild.setEnabled(false);
+
+ testSourceBuildList.getElement().getStyle().setProperty("minWidth", "15em");
+
// Add the remaining widgets to the main panel
panel.add(jobName, "create_job_name");
panel.add(jobNameToolTip, "create_job_name");
panel.add(image_url, "create_image_url");
panel.add(image_urlToolTip, "create_image_url");
+ panel.add(testSourceBuildList, "create_test_source_build");
+ panel.add(testSourceBuildListToolTip, "create_test_source_build");
panel.add(fetchImageTestsButton, "fetch_image_tests");
panel.add(testSelector, "create_tests");
panel.add(controlFilePanel, "create_edit_control");
@@ -310,6 +360,7 @@
panel.add(droneSet, "create_drone_set");
panel.add(advancedOptionsPanel, "create_advanced_options");
+ panel.add(firmwareBuildOptionsPanel, "create_firmware_build_options");
}
public CheckBoxPanel.Display getCheckBoxPanelDisplay() {
@@ -451,4 +502,16 @@
public HasClickHandlers getFetchImageTestsButton() {
return fetchImageTestsButton;
}
+
+ public ITextBox getFirmwareRWBuild() {
+ return firmwareRWBuild;
+ }
+
+ public ITextBox getFirmwareROBuild() {
+ return firmwareROBuild;
+ }
+
+ public ExtendedListBox getTestSourceBuildList() {
+ return testSourceBuildList;
+ }
}
diff --git a/frontend/client/src/autotest/afe/create/CreateJobViewPresenter.java b/frontend/client/src/autotest/afe/create/CreateJobViewPresenter.java
index 104b815..59d3c19 100644
--- a/frontend/client/src/autotest/afe/create/CreateJobViewPresenter.java
+++ b/frontend/client/src/autotest/afe/create/CreateJobViewPresenter.java
@@ -94,12 +94,18 @@
public HasClickHandlers getCreateTemplateJobButton();
public HasClickHandlers getResetButton();
public HasClickHandlers getFetchImageTestsButton();
+ public ITextBox getFirmwareRWBuild();
+ public ITextBox getFirmwareROBuild();
+ public ExtendedListBox getTestSourceBuildList();
}
private static final String EDIT_CONTROL_STRING = "Edit control file";
private static final String UNEDIT_CONTROL_STRING= "Revert changes";
private static final String VIEW_CONTROL_STRING = "View control file";
private static final String HIDE_CONTROL_STRING = "Hide control file";
+ private static final String FIRMWARE_RW_BUILD = "firmware_rw_build";
+ private static final String FIRMWARE_RO_BUILD = "firmware_ro_build";
+ private static final String TEST_SOURCE_BUILD = "test_source_build";
public interface JobCreateListener {
public void onJobCreated(int jobId);
@@ -167,8 +173,37 @@
display.getJobName().setText(jobObject.get("name").isString().stringValue());
+ ArrayList<String> builds = new ArrayList<String>();
if (jobObject.containsKey("image")) {
- display.getImageUrl().setText(jobObject.get("image").isString().stringValue());
+ String image = jobObject.get("image").isString().stringValue();
+ builds.add(image);
+ display.getImageUrl().setText(image);
+ display.getFirmwareRWBuild().setEnabled(true);
+ display.getFirmwareROBuild().setEnabled(true);
+ display.getTestSourceBuildList().setEnabled(true);
+ }
+
+ if (jobObject.containsKey(FIRMWARE_RW_BUILD)) {
+ String firmwareRWBuild = jobObject.get(FIRMWARE_RW_BUILD).isString().stringValue();
+ builds.add(firmwareRWBuild);
+ display.getFirmwareRWBuild().setText(firmwareRWBuild);
+ }
+
+ if (jobObject.containsKey(FIRMWARE_RO_BUILD)) {
+ String firmwareROBuild = jobObject.get(FIRMWARE_RO_BUILD).isString().stringValue();
+ builds.add(firmwareROBuild);
+ display.getFirmwareROBuild().setText(firmwareROBuild);
+ }
+
+ for (String build : builds) {
+ display.getTestSourceBuildList().addItem(build);
+ }
+
+ if (jobObject.containsKey(TEST_SOURCE_BUILD)) {
+ String testSourceBuild = jobObject.get(TEST_SOURCE_BUILD).isString().stringValue();
+ if (builds.indexOf(testSourceBuild) >= 0) {
+ display.getTestSourceBuildList().setSelectedIndex(builds.indexOf(testSourceBuild));
+ }
}
Double priorityValue = jobObject.get("priority").isNumber().getValue();
@@ -431,6 +466,47 @@
return maxRetries;
}
+ protected void handleBuildChange() {
+ ChangeHandler handler = new ChangeHandler() {
+ @Override
+ public void onChange(ChangeEvent event) {
+ String image = display.getImageUrl().getText();
+ if (image.isEmpty()) {
+ display.getFirmwareRWBuild().setText("");
+ display.getFirmwareROBuild().setText("");
+ display.getTestSourceBuildList().clear();
+ display.getFirmwareRWBuild().setEnabled(false);
+ display.getFirmwareROBuild().setEnabled(false);
+ display.getTestSourceBuildList().setEnabled(false);
+ }
+ else {
+ display.getFirmwareRWBuild().setEnabled(true);
+ display.getFirmwareROBuild().setEnabled(true);
+ display.getTestSourceBuildList().setEnabled(true);
+ ArrayList<String> builds = new ArrayList<String>();
+ builds.add(image);
+ if (!display.getFirmwareRWBuild().getText().isEmpty())
+ builds.add(display.getFirmwareRWBuild().getText());
+ if (!display.getFirmwareROBuild().getText().isEmpty())
+ builds.add(display.getFirmwareROBuild().getText());
+ String currentTestSourceBuild = display.getTestSourceBuildList().getSelectedValue();
+ int testSourceBuildIndex = builds.indexOf(currentTestSourceBuild);
+ display.getTestSourceBuildList().clear();
+ for (String build : builds) {
+ display.getTestSourceBuildList().addItem(build);
+ }
+ if (testSourceBuildIndex >= 0) {
+ display.getTestSourceBuildList().setSelectedIndex(testSourceBuildIndex);
+ }
+ }
+ }
+ };
+
+ display.getImageUrl().addChangeHandler(handler);
+ display.getFirmwareRWBuild().addChangeHandler(handler);
+ display.getFirmwareROBuild().addChangeHandler(handler);
+ }
+
protected void setInputsEnabled() {
testSelector.setEnabled(true);
profilersPanel.setEnabled(true);
@@ -586,6 +662,8 @@
}
});
+ handleBuildChange();
+
reset();
if (staticData.getData("drone_sets_enabled").isBoolean().booleanValue()) {
@@ -743,6 +821,29 @@
}
}
+ String firmwareRWBuild = display.getFirmwareRWBuild().getText();
+ String firmwareROBuild = display.getFirmwareROBuild().getText();
+ String testSourceBuild = display.getTestSourceBuildList().getSelectedValue();
+ if (!firmwareRWBuild.isEmpty() || !firmwareROBuild.isEmpty()) {
+ String error = "";
+ if (testSourceBuild.isEmpty())
+ error = "You must specify which build should be used to retrieve test code.";
+
+ // TODO(crbug.com/502638): Enable create test job with updating firmware.
+ if (!display.getHostless().getValue())
+ error = "Only suite job supports updating both ChromeOS build and firmware build.";
+ if (error != "") {
+ display.getSubmitJobButton().setEnabled(true);
+ NotifyManager.getInstance().showError(error);
+ return;
+ }
+ if (!firmwareRWBuild.isEmpty())
+ args.put(FIRMWARE_RW_BUILD, new JSONString(firmwareRWBuild));
+ if (!firmwareROBuild.isEmpty())
+ args.put(FIRMWARE_RO_BUILD, new JSONString(firmwareROBuild));
+ args.put(TEST_SOURCE_BUILD, new JSONString(testSourceBuild));
+ }
+
rpcProxy.rpcCall("create_job_page_handler", args, new JsonRpcCallback() {
@Override
public void onSuccess(JSONValue result) {
diff --git a/frontend/client/src/autotest/public/AfeClient.html b/frontend/client/src/autotest/public/AfeClient.html
index 9d3d9b3..00c5079 100644
--- a/frontend/client/src/autotest/public/AfeClient.html
+++ b/frontend/client/src/autotest/public/AfeClient.html
@@ -185,6 +185,17 @@
<tr class="data-row data-row-alternate">
<td class="field-name">Image URL/Build: (optional)</td>
<td class="has-tooltip" id="create_image_url"></td>
+ </tr>
+ </table>
+ <br>
+
+ <div id="create_firmware_build_options"></div>
+ <br>
+
+ <table class="data-table data-table-outlined-gray panel-boundedwidth">
+ <tr class="data-row data-row-alternate">
+ <td class="field-name">Test source build: (optional)</td>
+ <td class="has-tooltip" id="create_test_source_build"></td>
<td class="button" id="fetch_image_tests"></td>
</tr>
</table>