diff options
author | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-02-12 03:12:56 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-02-12 03:12:56 +0000 |
commit | 8788c8682a936dc325d7e878c727852d7b45121c (patch) | |
tree | c9ac6eaadcfa4a78698262cb2d8b941d5a8d48f7 | |
parent | cb0d7c45d344d4f5473a7d15bd4a9922ff8adbe9 (diff) | |
parent | f6426cf56357c6239e49a6ae2fde6bef8d70d6d7 (diff) | |
download | acloud-8788c8682a936dc325d7e878c727852d7b45121c.tar.gz |
acloud: [WebRTC] Provide a webrtc parameter am: 4e2d9224ec am: af83510870 am: f6426cf563
Change-Id: Iab5a9a6871117a41ceafc34e7e971707714c8488
-rw-r--r-- | create/avd_spec.py | 10 | ||||
-rw-r--r-- | create/avd_spec_test.py | 17 | ||||
-rw-r--r-- | create/create_args.py | 20 | ||||
-rw-r--r-- | create/create_args_test.py | 79 | ||||
-rw-r--r-- | create/local_image_remote_instance.py | 4 | ||||
-rw-r--r-- | create/remote_image_remote_instance.py | 3 | ||||
-rwxr-xr-x | internal/constants.py | 1 | ||||
-rw-r--r-- | internal/lib/cvd_compute_client_multi_stage.py | 13 | ||||
-rw-r--r-- | internal/lib/cvd_compute_client_multi_stage_test.py | 6 | ||||
-rwxr-xr-x | internal/lib/utils.py | 23 |
10 files changed, 160 insertions, 16 deletions
diff --git a/create/avd_spec.py b/create/avd_spec.py index 78e8462e..fed31a5a 100644 --- a/create/avd_spec.py +++ b/create/avd_spec.py @@ -662,13 +662,21 @@ class AVDSpec(object): @property def connect_vnc(self): - """launch vnc. + """Launch vnc. Return: Boolean, True if self._autoconnect is 'vnc'. """ return self._autoconnect == constants.INS_KEY_VNC @property + def connect_webrtc(self): + """Auto-launch webRTC AVD on the browser. + + Return: Boolean, True if args.autoconnect is "webrtc". + """ + return self._autoconnect == constants.INS_KEY_WEBRTC + + @property def unlock_screen(self): """Return unlock_screen.""" return self._unlock_screen diff --git a/create/avd_spec_test.py b/create/avd_spec_test.py index 26756c2b..0c323f55 100644 --- a/create/avd_spec_test.py +++ b/create/avd_spec_test.py @@ -354,21 +354,30 @@ class AvdSpecTest(driver_test_lib.BaseDriverTest): self.AvdSpec._ProcessMiscArgs(self.args) self.assertEqual(self.AvdSpec._instance_type, constants.INSTANCE_TYPE_HOST) - # Test avd_spec.autoconnect and avd_spec.connect_vnc + # Test avd_spec.autoconnect + self.args.autoconnect = False + self.AvdSpec._ProcessMiscArgs(self.args) + self.assertEqual(self.AvdSpec.autoconnect, False) + self.assertEqual(self.AvdSpec.connect_vnc, False) + self.assertEqual(self.AvdSpec.connect_webrtc, False) + self.args.autoconnect = constants.INS_KEY_VNC self.AvdSpec._ProcessMiscArgs(self.args) self.assertEqual(self.AvdSpec.autoconnect, True) self.assertEqual(self.AvdSpec.connect_vnc, True) + self.assertEqual(self.AvdSpec.connect_webrtc, False) - self.args.autoconnect = False + self.args.autoconnect = constants.INS_KEY_ADB self.AvdSpec._ProcessMiscArgs(self.args) - self.assertEqual(self.AvdSpec.autoconnect, False) + self.assertEqual(self.AvdSpec.autoconnect, True) self.assertEqual(self.AvdSpec.connect_vnc, False) + self.assertEqual(self.AvdSpec.connect_webrtc, False) - self.args.autoconnect = constants.INS_KEY_ADB + self.args.autoconnect = constants.INS_KEY_WEBRTC self.AvdSpec._ProcessMiscArgs(self.args) self.assertEqual(self.AvdSpec.autoconnect, True) self.assertEqual(self.AvdSpec.connect_vnc, False) + self.assertEqual(self.AvdSpec.connect_webrtc, True) if __name__ == "__main__": diff --git a/create/create_args.py b/create/create_args.py index 06aaaf6b..5bbab572 100644 --- a/create/create_args.py +++ b/create/create_args.py @@ -56,12 +56,15 @@ def AddCommonCreateArgs(parser): const=constants.INS_KEY_VNC, dest="autoconnect", required=False, - choices=[constants.INS_KEY_VNC, constants.INS_KEY_ADB], - help="For each remote instance, automatically create 2 ssh tunnels " - "forwarding both adb & vnc, and then add the device to adb. " - "For local cuttlefish instance, create a vnc connection. " - "For local goldfish instance, create a window." - "If need adb only, you can pass in 'adb' here.") + choices=[constants.INS_KEY_VNC, constants.INS_KEY_ADB, + constants.INS_KEY_WEBRTC], + help="Determines to establish a tunnel forwarding adb/vnc and " + "launch VNC/webrtc. Establish a tunnel forwarding adb and vnc " + "then launch vnc if --autoconnect vnc is provided. Establish a " + "tunnel forwarding adb if --autoconnect adb is provided. " + "Establish a tunnel forwarding adb and auto-launch on the browser " + "if --autoconnect webrtc is provided. For local goldfish " + "instance, create a window.") parser.add_argument( "--no-autoconnect", action="store_false", @@ -486,6 +489,11 @@ def _VerifyLocalArgs(args): raise errors.CheckPathError( "Specified path doesn't exist: %s" % tool_dir) + if args.autoconnect == constants.INS_KEY_WEBRTC: + if args.avd_type != constants.TYPE_CF: + raise errors.UnsupportedCreateArgs( + "'--autoconnect webrtc' only support cuttlefish.") + def _VerifyHostArgs(args): """Verify args starting with --host. diff --git a/create/create_args_test.py b/create/create_args_test.py new file mode 100644 index 00000000..8cca9ee2 --- /dev/null +++ b/create/create_args_test.py @@ -0,0 +1,79 @@ +# Copyright 2020 - The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for create.""" + +import unittest +import mock + +from acloud import errors +from acloud.create import create_args +from acloud.internal import constants +from acloud.internal.lib import driver_test_lib + + +def _CreateArgs(): + """set default pass in arguments.""" + mock_args = mock.MagicMock( + flavor=None, + num=None, + adb_port=None, + hw_property=None, + stable_cheeps_host_image_name=None, + stable_cheeps_host_image_project=None, + username=None, + password=None, + local_image="", + local_system_image="", + system_branch=None, + system_build_id=None, + system_build_target=None, + local_instance=None, + remote_host=None, + host_user=constants.GCE_USER, + host_ssh_private_key_path=None, + avd_type=constants.TYPE_CF, + autoconnect=constants.INS_KEY_VNC) + return mock_args + + +# pylint: disable=invalid-name,protected-access +class CreateArgsTest(driver_test_lib.BaseDriverTest): + """Test create_args functions.""" + + def testVerifyArgs(self): + """test VerifyArgs.""" + mock_args = _CreateArgs() + # Test args default setting shouldn't raise error. + self.assertEqual(None, create_args.VerifyArgs(mock_args)) + + def testVerifyArgs_ConnectWebRTC(self): + """test VerifyArgs args.autconnect webrtc. + + WebRTC only apply to remote cuttlefish instance + + """ + mock_args = _CreateArgs() + mock_args.autoconnect = constants.INS_KEY_WEBRTC + # Test remote instance and avd_type cuttlefish(default) + # Test args.autoconnect webrtc shouldn't raise error. + self.assertEqual(None, create_args.VerifyArgs(mock_args)) + + # Test pass in none-cuttlefish avd_type should raise error. + mock_args.avd_type = constants.TYPE_GF + self.assertRaises(errors.UnsupportedCreateArgs, + create_args.VerifyArgs, mock_args) + + +if __name__ == "__main__": + unittest.main() diff --git a/create/local_image_remote_instance.py b/create/local_image_remote_instance.py index 510073de..8177f716 100644 --- a/create/local_image_remote_instance.py +++ b/create/local_image_remote_instance.py @@ -18,7 +18,6 @@ r"""LocalImageRemoteInstance class. Create class that is responsible for creating a remote instance AVD with a local image. """ - from acloud.create import create_common from acloud.create import base_avd_create from acloud.internal import constants @@ -57,4 +56,7 @@ class LocalImageRemoteInstance(base_avd_create.BaseAVDCreate): # Launch vnc client if we're auto-connecting. if avd_spec.connect_vnc: utils.LaunchVNCFromReport(report, avd_spec, no_prompts) + if avd_spec.connect_webrtc: + utils.LaunchBrowserFromReport(report) + return report diff --git a/create/remote_image_remote_instance.py b/create/remote_image_remote_instance.py index 13d24ad9..633d32ec 100644 --- a/create/remote_image_remote_instance.py +++ b/create/remote_image_remote_instance.py @@ -18,7 +18,6 @@ r"""RemoteImageRemoteInstance class. Create class that is responsible for creating a remote instance AVD with a remote image. """ - from acloud.create import base_avd_create from acloud.internal.lib import utils from acloud.public.actions import common_operations @@ -54,5 +53,7 @@ class RemoteImageRemoteInstance(base_avd_create.BaseAVDCreate): # Launch vnc client if we're auto-connecting. if avd_spec.connect_vnc: utils.LaunchVNCFromReport(report, avd_spec, no_prompts) + if avd_spec.connect_webrtc: + utils.LaunchBrowserFromReport(report) return report diff --git a/internal/constants.py b/internal/constants.py index deffde5f..fb95d44b 100755 --- a/internal/constants.py +++ b/internal/constants.py @@ -141,6 +141,7 @@ INS_KEY_DISPLAY = "display" INS_KEY_IP = "ip" INS_KEY_ADB = "adb" INS_KEY_VNC = "vnc" +INS_KEY_WEBRTC = "webrtc" INS_KEY_CREATETIME = "creationTimestamp" INS_KEY_AVD_TYPE = "avd_type" INS_KEY_AVD_FLAVOR = "flavor" diff --git a/internal/lib/cvd_compute_client_multi_stage.py b/internal/lib/cvd_compute_client_multi_stage.py index 01d4c0ed..e833ad9b 100644 --- a/internal/lib/cvd_compute_client_multi_stage.py +++ b/internal/lib/cvd_compute_client_multi_stage.py @@ -62,6 +62,12 @@ _FETCHER_NAME = "fetch_cvd" _FETCH_ARTIFACT = "fetch_artifact_time" _GCE_CREATE = "gce_create_time" _LAUNCH_CVD = "launch_cvd_time" +# WebRTC args for launching AVD +_GUEST_ENFORCE_SECURITY_FALSE = "--guest_enforce_security=false" +_START_WEBRTC = "--start_webrtc" +_VM_MANAGER = "--vm_manager=crosvm" +_WEBRTC_ARGS = [_GUEST_ENFORCE_SECURITY_FALSE, _START_WEBRTC, _VM_MANAGER] +_WEBRTC_PUBLIC_IP = "--webrtc_public_ip=%s" def _ProcessBuild(build_id=None, branch=None, build_target=None): @@ -266,6 +272,9 @@ class CvdComputeClient(android_compute_client.AndroidComputeClient): if constants.HW_ALIAS_MEMORY in avd_spec.hw_property: launch_cvd_args.append( "-memory_mb=%s" % avd_spec.hw_property[constants.HW_ALIAS_MEMORY]) + if avd_spec.connect_webrtc: + launch_cvd_args.append(_WEBRTC_PUBLIC_IP % self._ip.external) + launch_cvd_args.extend(_WEBRTC_ARGS) else: resolution = self._resolution.split("x") launch_cvd_args.append("-x_res=" + resolution[0]) @@ -447,7 +456,9 @@ class CvdComputeClient(android_compute_client.AndroidComputeClient): network=self._network, zone=self._zone, gpu=self._gpu, - extra_scopes=extra_scopes) + extra_scopes=extra_scopes, + tags=["appstreaming"] if ( + avd_spec and avd_spec.connect_webrtc) else None) ip = gcompute_client.ComputeClient.GetInstanceIP( self, instance=instance, zone=self._zone) logger.debug("'instance_ip': %s", ip.internal diff --git a/internal/lib/cvd_compute_client_multi_stage_test.py b/internal/lib/cvd_compute_client_multi_stage_test.py index feb2bdf1..b83bafb5 100644 --- a/internal/lib/cvd_compute_client_multi_stage_test.py +++ b/internal/lib/cvd_compute_client_multi_stage_test.py @@ -182,7 +182,8 @@ class CvdComputeClientTest(driver_test_lib.BaseDriverTest): network=self.NETWORK, zone=self.ZONE, extra_scopes=self.EXTRA_SCOPES, - gpu=self.GPU) + gpu=self.GPU, + tags=None) mock_check_img.return_value = True #test use local image in the remote instance. @@ -215,7 +216,8 @@ class CvdComputeClientTest(driver_test_lib.BaseDriverTest): network=self.NETWORK, zone=self.ZONE, extra_scopes=self.EXTRA_SCOPES, - gpu=self.GPU) + gpu=self.GPU, + tags=None) if __name__ == "__main__": diff --git a/internal/lib/utils.py b/internal/lib/utils.py index 1342cbf4..e6790d33 100755 --- a/internal/lib/utils.py +++ b/internal/lib/utils.py @@ -36,6 +36,7 @@ import tarfile import tempfile import time import uuid +import webbrowser import zipfile import six @@ -86,6 +87,10 @@ _SSVNC_ENV_VARS = {"SSVNC_NO_ENC_WARN": "1", "SSVNC_SCALE": "auto", "VNCVIEWER_X _DEFAULT_DISPLAY_SCALE = 1.0 _DIST_DIR = "DIST_DIR" +# For webrtc +_WEBRTC_URL = "https://" +_WEBRTC_PORT = "8443" + _CONFIRM_CONTINUE = ("In order to display the screen to the AVD, we'll need to " "install a vnc client (ssvnc). \nWould you like acloud to " "install it for you? (%s) \nPress 'y' to continue or " @@ -796,6 +801,7 @@ def _ExecuteCommand(cmd, args): subprocess.check_call(command, stderr=dev_null, stdout=dev_null) +# TODO(147337696): create ssh tunnels tear down as adb and vnc. # pylint: disable=too-many-locals def AutoConnect(ip_addr, rsa_key_file, target_vnc_port, target_adb_port, ssh_user, client_adb_port=None, extra_args_ssh_tunnel=None): @@ -905,6 +911,23 @@ def LaunchVNCFromReport(report, avd_spec, no_prompts=False): PrintColorString("No VNC port specified, skipping VNC startup.", TextColors.FAIL) +def LaunchBrowserFromReport(report): + """Open browser when autoconnect to webrtc according to the instances report. + + Args: + report: Report object, that stores and generates report. + """ + for device in report.data.get("devices", []): + if device.get("ip"): + PrintColorString("(This is an experimental project for webrtc, and " + "since the certificate is self-signed, Chrome will " + "mark it as an insecure website. keep going.)", + TextColors.WARNING) + webbrowser.open_new_tab("%s%s:%s" % ( + _WEBRTC_URL, device.get("ip"), _WEBRTC_PORT)) + else: + PrintColorString("Auto-launch devices webrtc in browser failed!", + TextColors.FAIL) def LaunchVncClient(port, avd_width=None, avd_height=None, no_prompts=False): """Launch ssvnc. |