Merge "Support to get WebRTC server port for remote instance."
diff --git a/.coveragerc b/.coveragerc
index 42077e0..db9bf37 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -16,6 +16,9 @@
# TODO: Remove the bottom 2 when the files are deleted.
*public/__main__.py
*setup.py
+ # gce is not support now.
+ *create/gce_local_image_remote_instance.py
+ *create/gce_remote_image_remote_instance.py
[report]
# Regexes for lines to exclude from consideration
diff --git a/create/avd_spec.py b/create/avd_spec.py
index 203b136..40766a3 100644
--- a/create/avd_spec.py
+++ b/create/avd_spec.py
@@ -111,6 +111,7 @@
self._extra_files = None
self._avd_type = None
self._flavor = None
+ self._force_sync = None
self._image_source = None
self._instance_type = None
self._launch_args = None
@@ -322,6 +323,7 @@
self._avd_type = args.avd_type
self._extra_files = create_common.ParseExtraFilesArgs(args.extra_files)
self._flavor = args.flavor or constants.FLAVOR_PHONE
+ self._force_sync = args.force_sync
if args.remote_host:
self._instance_type = constants.INSTANCE_TYPE_HOST
else:
@@ -1024,3 +1026,8 @@
def mkcert(self):
"""Return mkcert."""
return self._mkcert
+
+ @property
+ def force_sync(self):
+ """Return force_sync."""
+ return self._force_sync
diff --git a/create/create_args.py b/create/create_args.py
index c581a70..ffbe0bb 100644
--- a/create/create_args.py
+++ b/create/create_args.py
@@ -125,6 +125,13 @@
required=False,
help="Skip the pre-run check.")
parser.add_argument(
+ "--force-sync",
+ action="store_true",
+ dest="force_sync",
+ required=False,
+ help="Force to sync image files from Android Build servers even if "
+ "they are already existed for local instance mode.")
+ parser.add_argument(
"--boot-timeout",
dest="boot_timeout_secs",
type=int,
diff --git a/create/local_image_remote_host_test.py b/create/local_image_remote_host_test.py
new file mode 100644
index 0000000..15af6db
--- /dev/null
+++ b/create/local_image_remote_host_test.py
@@ -0,0 +1,65 @@
+# Copyright 2021 - 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 LocalImageRemoteHost."""
+
+import unittest
+
+from unittest import mock
+
+from acloud.create import avd_spec
+from acloud.create import create
+from acloud.create import create_common
+from acloud.create import local_image_remote_host
+from acloud.internal import constants
+from acloud.internal.lib import driver_test_lib
+from acloud.internal.lib import utils
+from acloud.public.actions import common_operations
+from acloud.public.actions import remote_instance_cf_device_factory
+
+class LocalImageRemoteHostTest(driver_test_lib.BaseDriverTest):
+ """Test LocalImageRemoteHost method."""
+
+ def setUp(self):
+ """Initialize new LocalImageRemoteHost."""
+ super().setUp()
+ self.local_image_remote_host = local_image_remote_host.LocalImageRemoteHost()
+
+ # pylint: disable=no-member
+ def testRun(self):
+ """Test Create AVD of cuttlefish local image remote host."""
+ args = mock.MagicMock()
+ args.skip_pre_run_check = True
+ spec = mock.MagicMock()
+ spec.avd_type = constants.TYPE_CF
+ spec.instance_type = constants.INSTANCE_TYPE_HOST
+ spec.image_source = constants.IMAGE_SRC_LOCAL
+ spec.connect_vnc = False
+ self.Patch(avd_spec, "AVDSpec", return_value=spec)
+ self.Patch(remote_instance_cf_device_factory,
+ "RemoteInstanceDeviceFactory")
+ self.Patch(create_common, "GetCvdHostPackage")
+ self.Patch(common_operations, "CreateDevices")
+ create.Run(args)
+ remote_instance_cf_device_factory.RemoteInstanceDeviceFactory.assert_called_once()
+ common_operations.CreateDevices.assert_called_once()
+
+ spec.connect_vnc = True
+ self.Patch(avd_spec, "AVDSpec", return_value=spec)
+ self.Patch(utils, "LaunchVNCFromReport")
+ create.Run(args)
+ utils.LaunchVNCFromReport.assert_called_once()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/create/remote_image_local_instance.py b/create/remote_image_local_instance.py
index fcb0f5c..8d989a8 100644
--- a/create/remote_image_local_instance.py
+++ b/create/remote_image_local_instance.py
@@ -79,7 +79,7 @@
logger.debug("Extract path: %s", extract_path)
- if os.path.exists(extract_path):
+ if avd_spec.force_sync and os.path.exists(extract_path):
shutil.rmtree(extract_path)
if not os.path.exists(extract_path):
os.makedirs(extract_path)
diff --git a/create/remote_image_local_instance_test.py b/create/remote_image_local_instance_test.py
index 5697f4e..8eda639 100644
--- a/create/remote_image_local_instance_test.py
+++ b/create/remote_image_local_instance_test.py
@@ -16,6 +16,7 @@
import unittest
from collections import namedtuple
import os
+import shutil
import subprocess
from unittest import mock
@@ -69,18 +70,20 @@
self.assertEqual(paths.image_dir, "/unit/test")
self.assertEqual(paths.host_bins, "/unit/test")
- def testDownloadAndProcessImageFiles(self):
+ @mock.patch.object(shutil, "rmtree")
+ def testDownloadAndProcessImageFiles(self, mock_rmtree):
"""Test process remote cuttlefish image."""
avd_spec = mock.MagicMock()
avd_spec.cfg = mock.MagicMock()
avd_spec.cfg.creds_cache_file = "cache.file"
avd_spec.remote_image = self._fake_remote_image
avd_spec.image_download_dir = "/tmp"
- self.Patch(os.path, "exists", return_value=False)
+ avd_spec.force_sync = True
+ self.Patch(os.path, "exists", side_effect=[True, False])
self.Patch(os, "makedirs")
self.Patch(subprocess, "check_call")
remote_image_local_instance.DownloadAndProcessImageFiles(avd_spec)
-
+ self.assertEqual(mock_rmtree.call_count, 1)
self.assertEqual(self.build_client.GetFetchBuildArgs.call_count, 1)
self.assertEqual(self.build_client.GetFetchCertArg.call_count, 1)
diff --git a/create/remote_image_remote_host_test.py b/create/remote_image_remote_host_test.py
index e69de29..1f665e7 100644
--- a/create/remote_image_remote_host_test.py
+++ b/create/remote_image_remote_host_test.py
@@ -0,0 +1,63 @@
+# Copyright 2021 - 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 RemoteImageRemoteHost."""
+
+import unittest
+
+from unittest import mock
+
+from acloud.create import avd_spec
+from acloud.create import create
+from acloud.create import remote_image_remote_host
+from acloud.internal import constants
+from acloud.internal.lib import driver_test_lib
+from acloud.internal.lib import utils
+from acloud.public.actions import common_operations
+from acloud.public.actions import remote_instance_cf_device_factory
+
+class RemoteImageRemoteHostTest(driver_test_lib.BaseDriverTest):
+ """Test RemoteImageRemoteHost method."""
+
+ def setUp(self):
+ """Initialize new RemoteImageRemoteHost."""
+ super().setUp()
+ self.remote_image_remote_host = remote_image_remote_host.RemoteImageRemoteHost()
+
+ # pylint: disable=no-member
+ def testRun(self):
+ """Test Create AVD of cuttlefish remote image remote Host."""
+ args = mock.MagicMock()
+ args.skip_pre_run_check = True
+ spec = mock.MagicMock()
+ spec.avd_type = constants.TYPE_CF
+ spec.instance_type = constants.INSTANCE_TYPE_HOST
+ spec.image_source = constants.IMAGE_SRC_REMOTE
+ spec.connect_vnc = False
+ self.Patch(avd_spec, "AVDSpec", return_value=spec)
+ self.Patch(remote_instance_cf_device_factory,
+ "RemoteInstanceDeviceFactory")
+ self.Patch(common_operations, "CreateDevices")
+ create.Run(args)
+ remote_instance_cf_device_factory.RemoteInstanceDeviceFactory.assert_called_once()
+ common_operations.CreateDevices.assert_called_once()
+
+ spec.connect_vnc = True
+ self.Patch(avd_spec, "AVDSpec", return_value=spec)
+ self.Patch(utils, "LaunchVNCFromReport")
+ create.Run(args)
+ utils.LaunchVNCFromReport.assert_called_once()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/internal/lib/utils.py b/internal/lib/utils.py
index c7a4610..cf7c2d9 100755
--- a/internal/lib/utils.py
+++ b/internal/lib/utils.py
@@ -74,7 +74,8 @@
_PORT_1443 = 1443
PortMapping = collections.namedtuple("PortMapping", ["local", "target"])
WEBRTC_PORTS_MAPPING = [PortMapping(15550, 15550),
- PortMapping(15551, 15551)]
+ PortMapping(15551, 15551),
+ PortMapping(15552, 15552)]
# Use mkcert to generate a localhost certificates for webrtc
_MKCERT_LOCAL_CERT_CMD = ("%(local_ca_dir)s/mkcert "
"-key-file %(local_ca_dir)s/server.key "
diff --git a/internal/lib/utils_test.py b/internal/lib/utils_test.py
index 9eb624f..9b26ab1 100644
--- a/internal/lib/utils_test.py
+++ b/internal/lib/utils_test.py
@@ -441,6 +441,7 @@
mock_establish_ssh_tunnel = self.Patch(utils, "EstablishSshTunnel")
fake_port_mapping = [utils.PortMapping(15550, 15550),
utils.PortMapping(15551, 15551),
+ utils.PortMapping(15552, 15552),
utils.PortMapping(12345, 8443)]
utils.EstablishWebRTCSshTunnel(