[autotest] Support uploading a service key file to moblab
Add RPC to accept an uploaded key file and save it to
/home/moblab/.launch_control_key
Add a new tab in moblab setup page to allow user to upload a service key file.
BUG=chromium:570705
TEST=verify with a local moblab build
Change-Id: Ib54a6b707cb93bb5220e29ed6feeb854f5f4abe8
Reviewed-on: https://chromium-review.googlesource.com/321140
Commit-Ready: Dan Shi <dshi@google.com>
Tested-by: Dan Shi <dshi@google.com>
Reviewed-by: Simran Basi <sbasi@chromium.org>
diff --git a/frontend/afe/site_rpc_interface.py b/frontend/afe/site_rpc_interface.py
index a7cb19a..e0a7e0a 100644
--- a/frontend/afe/site_rpc_interface.py
+++ b/frontend/afe/site_rpc_interface.py
@@ -325,6 +325,22 @@
shutil.copyfile(boto_key, moblab_host.MOBLAB_BOTO_LOCATION)
+@moblab_only
+def set_launch_control_key(launch_control_key):
+ """Update the launch_control_key file.
+
+ @param launch_control_key: File name of launch_control_key uploaded through
+ handle_file_upload.
+ """
+ if not os.path.exists(launch_control_key):
+ raise error.RPCException('Launch Control key: %s does not exist!' %
+ launch_control_key)
+ shutil.copyfile(launch_control_key,
+ moblab_host.MOBLAB_LAUNCH_CONTROL_KEY_LOCATION)
+ # Restart the devserver service.
+ os.system('sudo restart moblab-devserver-init')
+
+
def get_job_history(**filter_data):
"""Get history of the job, including the special tasks executed for the job
diff --git a/frontend/afe/site_rpc_interface_unittest.py b/frontend/afe/site_rpc_interface_unittest.py
index df87752..0606dbe 100755
--- a/frontend/afe/site_rpc_interface_unittest.py
+++ b/frontend/afe/site_rpc_interface_unittest.py
@@ -27,6 +27,7 @@
from autotest_lib.server import utils
from autotest_lib.server.cros.dynamic_suite import control_file_getter
from autotest_lib.server.cros.dynamic_suite import constants
+from autotest_lib.server.hosts import moblab_host
CLIENT = control_data.CONTROL_TYPE_NAMES.CLIENT
@@ -447,6 +448,24 @@
site_rpc_interface.set_boto_key(boto_key)
+ def testSetLaunchControlKey(self):
+ """Ensure that the Launch Control key path supplied is copied correctly.
+ """
+ self.setIsMoblab(True)
+ launch_control_key = '/tmp/launch_control'
+ site_rpc_interface.os = self.mox.CreateMockAnything()
+ site_rpc_interface.os.path = self.mox.CreateMockAnything()
+ site_rpc_interface.os.path.exists(launch_control_key).AndReturn(
+ True)
+ site_rpc_interface.shutil = self.mox.CreateMockAnything()
+ site_rpc_interface.shutil.copyfile(
+ launch_control_key,
+ moblab_host.MOBLAB_LAUNCH_CONTROL_KEY_LOCATION)
+ site_rpc_interface.os.system('sudo restart moblab-devserver-init')
+ self.mox.ReplayAll()
+ site_rpc_interface.set_launch_control_key(launch_control_key)
+
+
def _get_records_for_sending_to_master(self):
return [{'control_file': 'foo',
'control_type': 1,
diff --git a/frontend/client/src/autotest/moblab/BotoKeyView.java b/frontend/client/src/autotest/moblab/BotoKeyView.java
index d8f6c48..03393f7 100644
--- a/frontend/client/src/autotest/moblab/BotoKeyView.java
+++ b/frontend/client/src/autotest/moblab/BotoKeyView.java
@@ -1,29 +1,6 @@
package autotest.moblab;
-import autotest.common.JsonRpcCallback;
-import autotest.common.JsonRpcProxy;
-import autotest.common.SimpleCallback;
-import autotest.common.ui.TabView;
-import autotest.common.ui.NotifyManager;
-
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONString;
-import com.google.gwt.json.client.JSONValue;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FileUpload;
-import com.google.gwt.user.client.ui.FormPanel;
-import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
-import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
-import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
-import com.google.gwt.user.client.ui.FormPanel.SubmitHandler;
-
-
-public class BotoKeyView extends TabView {
- private FileUpload botoKeyUpload;
- private Button submitButton;
- private FormPanel botoKeyUploadForm;
+public class BotoKeyView extends KeyUploadView {
@Override
public String getElementId() {
@@ -32,44 +9,13 @@
@Override
public void initialize() {
+ fileUploadName = "botokey";
+ uploadViewName = "view_boto_key";
+ submitButtonName = "view_submit_boto_key";
+ rpcName = "set_boto_key";
+ rpcArgName = "boto_key";
+ successMessage = "Boto Key uploaded.";
+
super.initialize();
-
- botoKeyUpload = new FileUpload();
- botoKeyUpload.setName("botokey");
-
- botoKeyUploadForm = new FormPanel();
- botoKeyUploadForm.setAction(JsonRpcProxy.AFE_BASE_URL + "upload/");
- botoKeyUploadForm.setEncoding(FormPanel.ENCODING_MULTIPART);
- botoKeyUploadForm.setMethod(FormPanel.METHOD_POST);
- botoKeyUploadForm.setWidget(botoKeyUpload);
-
- submitButton = new Button("Submit", new ClickHandler() {
- public void onClick(ClickEvent event) {
- botoKeyUploadForm.submit();
- }
- });
-
- botoKeyUploadForm.addSubmitCompleteHandler(new SubmitCompleteHandler() {
- public void onSubmitComplete(SubmitCompleteEvent event) {
- String fileName = event.getResults();
- JSONObject params = new JSONObject();
- params.put("boto_key", new JSONString(fileName));
- rpcCall(params);
- }
- });
-
- addWidget(botoKeyUploadForm, "view_boto_key");
- addWidget(submitButton, "view_submit_boto_key");
}
-
- public void rpcCall(JSONObject params) {
- JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
- rpcProxy.rpcCall("set_boto_key", params, new JsonRpcCallback() {
- @Override
- public void onSuccess(JSONValue result) {
- NotifyManager.getInstance().showMessage("Boto key uploaded.");
- }
- });
- }
-
-}
\ No newline at end of file
+}
diff --git a/frontend/client/src/autotest/moblab/KeyUploadView.java b/frontend/client/src/autotest/moblab/KeyUploadView.java
new file mode 100644
index 0000000..953144a
--- /dev/null
+++ b/frontend/client/src/autotest/moblab/KeyUploadView.java
@@ -0,0 +1,81 @@
+package autotest.moblab;
+
+import autotest.common.JsonRpcCallback;
+import autotest.common.JsonRpcProxy;
+import autotest.common.SimpleCallback;
+import autotest.common.ui.TabView;
+import autotest.common.ui.NotifyManager;
+
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.json.client.JSONObject;
+import com.google.gwt.json.client.JSONString;
+import com.google.gwt.json.client.JSONValue;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FileUpload;
+import com.google.gwt.user.client.ui.FormPanel;
+import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
+import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
+import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
+import com.google.gwt.user.client.ui.FormPanel.SubmitHandler;
+
+
+public class KeyUploadView extends TabView {
+ private FileUpload keyUpload;
+ private Button submitButton;
+ private FormPanel keyUploadForm;
+
+ protected String fileUploadName = "key";
+ protected String uploadViewName = "view_key";
+ protected String submitButtonName = "view_submit_key";
+ protected String rpcName = "";
+ protected String rpcArgName = "key";
+ protected String successMessage = "Key uploaded.";
+
+ @Override
+ public String getElementId() {
+ return "key";
+ }
+
+ @Override
+ public void initialize() {
+ super.initialize();
+
+ keyUpload = new FileUpload();
+ keyUpload.setName(fileUploadName);
+
+ keyUploadForm = new FormPanel();
+ keyUploadForm.setAction(JsonRpcProxy.AFE_BASE_URL + "upload/");
+ keyUploadForm.setEncoding(FormPanel.ENCODING_MULTIPART);
+ keyUploadForm.setMethod(FormPanel.METHOD_POST);
+ keyUploadForm.setWidget(keyUpload);
+
+ submitButton = new Button("Submit", new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ keyUploadForm.submit();
+ }
+ });
+
+ keyUploadForm.addSubmitCompleteHandler(new SubmitCompleteHandler() {
+ public void onSubmitComplete(SubmitCompleteEvent event) {
+ String fileName = event.getResults();
+ JSONObject params = new JSONObject();
+ params.put(rpcArgName, new JSONString(fileName));
+ rpcCall(params);
+ }
+ });
+
+ addWidget(keyUploadForm, uploadViewName);
+ addWidget(submitButton, submitButtonName);
+ }
+
+ public void rpcCall(JSONObject params) {
+ JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
+ rpcProxy.rpcCall(rpcName, params, new JsonRpcCallback() {
+ @Override
+ public void onSuccess(JSONValue result) {
+ NotifyManager.getInstance().showMessage(successMessage);
+ }
+ });
+ }
+}
diff --git a/frontend/client/src/autotest/moblab/LaunchControlKeyView.java b/frontend/client/src/autotest/moblab/LaunchControlKeyView.java
new file mode 100644
index 0000000..f193b50
--- /dev/null
+++ b/frontend/client/src/autotest/moblab/LaunchControlKeyView.java
@@ -0,0 +1,21 @@
+package autotest.moblab;
+
+public class LaunchControlKeyView extends KeyUploadView {
+
+ @Override
+ public String getElementId() {
+ return "launch_control_key";
+ }
+
+ @Override
+ public void initialize() {
+ fileUploadName = "launchcontrolkey";
+ uploadViewName = "view_launch_control_key";
+ submitButtonName = "view_submit_launch_control_key";
+ rpcName = "set_launch_control_key";
+ rpcArgName = "launch_control_key";
+ successMessage = "Launch Control Key uploaded.";
+
+ super.initialize();
+ }
+}
diff --git a/frontend/client/src/autotest/moblab/MoblabSetupClient.java b/frontend/client/src/autotest/moblab/MoblabSetupClient.java
index 3b07b15..e75982c 100644
--- a/frontend/client/src/autotest/moblab/MoblabSetupClient.java
+++ b/frontend/client/src/autotest/moblab/MoblabSetupClient.java
@@ -12,6 +12,7 @@
public class MoblabSetupClient implements EntryPoint {
private ConfigSettingsView configSettingsView;
private BotoKeyView botoKeyView;
+ private LaunchControlKeyView launchControlKeyView;
public CustomTabPanel mainTabPanel = new CustomTabPanel();
@@ -24,8 +25,10 @@
configSettingsView = new ConfigSettingsView();
botoKeyView = new BotoKeyView();
+ launchControlKeyView = new LaunchControlKeyView();
mainTabPanel.addTabView(configSettingsView);
mainTabPanel.addTabView(botoKeyView);
+ mainTabPanel.addTabView(launchControlKeyView);
final RootPanel rootPanel = RootPanel.get("tabs");
rootPanel.add(mainTabPanel);
@@ -33,4 +36,4 @@
rootPanel.setStyleName("");
}
-}
\ No newline at end of file
+}
diff --git a/frontend/client/src/autotest/public/MoblabSetupClient.html b/frontend/client/src/autotest/public/MoblabSetupClient.html
index 7f1599b..6afd4d7 100644
--- a/frontend/client/src/autotest/public/MoblabSetupClient.html
+++ b/frontend/client/src/autotest/public/MoblabSetupClient.html
@@ -25,9 +25,16 @@
<span id="view_boto_key"></span>
<span id="view_submit_boto_key"></span>
</div>
+
+ <div id="launch_control_key" title="Launch Control Key">
+ <span class="field-name">Launch Control Key: </span>
+ <span id="view_launch_control_key"></span>
+ <span id="view_submit_launch_control_key"></span>
+ </div>
+
</div>
<br>
<div id="error_log"></div>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/server/hosts/moblab_host.py b/server/hosts/moblab_host.py
index 010f683..7f0faff 100644
--- a/server/hosts/moblab_host.py
+++ b/server/hosts/moblab_host.py
@@ -24,6 +24,7 @@
'(?P<mac>[0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])')
MOBLAB_IMAGE_STORAGE = '/mnt/moblab/static'
MOBLAB_BOTO_LOCATION = '/home/moblab/.boto'
+MOBLAB_LAUNCH_CONTROL_KEY_LOCATION = '/home/moblab/.launch_control_key'
MOBLAB_AUTODIR = '/usr/local/autodir'
DHCPD_LEASE_FILE = '/var/lib/dhcp/dhcpd.leases'
MOBLAB_SERVICES = ['moblab-scheduler-init',