[autotest] Update stage_server_side_package to support restricted subnet.

If a dut is in restricted subnet, server-side packaging uses the devserver in
the same subnet of the dut. This leads to test failure as drone, which is
outside the restricted subnet, doesn't have http access to the devserver.

This change update method stage_server_side_package so it resolves a new
devserver outside restricted subnet if needed.

BUG=chromium:624554
TEST=local run test

Change-Id: I2c431fe7b0b8d4453978917e8a5e96fd310805f6
Reviewed-on: https://chromium-review.googlesource.com/358610
Commit-Ready: Dan Shi <dshi@google.com>
Tested-by: Dan Shi <dshi@google.com>
Reviewed-by: Simran Basi <sbasi@chromium.org>
diff --git a/server/hosts/adb_host.py b/server/hosts/adb_host.py
index eae37e7..e261394 100644
--- a/server/hosts/adb_host.py
+++ b/server/hosts/adb_host.py
@@ -1623,8 +1623,14 @@
                  server-side package is not supported.
         @raise: error.AutoservError if fail to locate the build to test with.
         """
+        # If enable_drone_in_restricted_subnet is False, do not set hostname
+        # in devserver.resolve call, so a devserver in non-restricted subnet
+        # is picked to stage autotest server package for drone to download.
+        hostname = self.hostname
+        if not utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
+            hostname = None
         if image:
-            ds = dev_server.AndroidBuildServer.resolve(image, self.hostname)
+            ds = dev_server.AndroidBuildServer.resolve(image, hostname)
         else:
             job_repo_url = afe_utils.get_host_attribute(
                     self, self.job_repo_url_attribute)
@@ -1632,7 +1638,13 @@
                 devserver_url, image = (
                         tools.get_devserver_build_from_package_url(
                                 job_repo_url, True))
-                ds = dev_server.AndroidBuildServer(devserver_url)
+                # If enable_drone_in_restricted_subnet is True, use the
+                # existing devserver. Otherwise, resolve a new one in
+                # non-restricted subnet.
+                if utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
+                    ds = dev_server.AndroidBuildServer(devserver_url)
+                else:
+                    ds = dev_server.AndroidBuildServer.resolve(image)
             else:
                 labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
                 if not labels:
@@ -1640,7 +1652,7 @@
                             'Failed to stage server-side package. The host has '
                             'no job_report_url attribute or version label.')
                 image = labels[0].name[len(self.VERSION_PREFIX)+1:]
-                ds = dev_server.AndroidBuildServer.resolve(image, self.hostname)
+                ds = dev_server.AndroidBuildServer.resolve(image, hostname)
 
         branch, target, build_id = utils.parse_launch_control_build(image)
         build_target, _ = utils.parse_launch_control_target(target)
diff --git a/server/hosts/cros_host.py b/server/hosts/cros_host.py
index db68973..6a277e8 100644
--- a/server/hosts/cros_host.py
+++ b/server/hosts/cros_host.py
@@ -456,29 +456,41 @@
 
         @return: A url to the autotest server-side package.
         """
+        # If enable_drone_in_restricted_subnet is False, do not set hostname
+        # in devserver.resolve call, so a devserver in non-restricted subnet
+        # is picked to stage autotest server package for drone to download.
+        hostname = self.hostname
+        if not server_utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
+            hostname = None
         if image:
             image_name = tools.get_build_from_image(image)
             if not image_name:
                 raise error.AutoservError(
                         'Failed to parse build name from %s' % image)
-            ds = dev_server.ImageServer.resolve(image_name, self.hostname)
+            ds = dev_server.ImageServer.resolve(image_name, hostname)
         else:
             job_repo_url = afe_utils.get_host_attribute(
                     self, ds_constants.JOB_REPO_URL)
             if job_repo_url:
                 devserver_url, image_name = (
                     tools.get_devserver_build_from_package_url(job_repo_url))
-                ds = dev_server.ImageServer(devserver_url)
+                # If enable_drone_in_restricted_subnet is True, use the
+                # existing devserver. Otherwise, resolve a new one in
+                # non-restricted subnet.
+                if server_utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
+                    ds = dev_server.ImageServer(devserver_url)
+                else:
+                    ds = dev_server.ImageServer.resolve(image_name)
             else:
                 labels = self._AFE.get_labels(
-                        name__startswith=ds_constants.VERSION_PREFIX,
+                        name__startswith=self.VERSION_PREFIX,
                         host__hostname=self.hostname)
                 if not labels:
                     raise error.AutoservError(
                             'Failed to stage server-side package. The host has '
                             'no job_report_url attribute or version label.')
-                image_name = labels[0].name[len(ds_constants.VERSION_PREFIX):]
-                ds = dev_server.ImageServer.resolve(image_name, self.hostname)
+                image_name = labels[0].name[len(self.VERSION_PREFIX):]
+                ds = dev_server.ImageServer.resolve(image_name, hostname)
 
         # Get the OS version of the build, for any build older than
         # MIN_VERSION_SUPPORT_SSP, server side packaging is not supported.
diff --git a/server/site_utils.py b/server/site_utils.py
index a040edf..804ccc6 100644
--- a/server/site_utils.py
+++ b/server/site_utils.py
@@ -31,15 +31,19 @@
     cros_build_lib = None
 
 
-_SHERIFF_JS = global_config.global_config.get_config_value(
-    'NOTIFICATIONS', 'sheriffs', default='')
-_LAB_SHERIFF_JS = global_config.global_config.get_config_value(
-    'NOTIFICATIONS', 'lab_sheriffs', default='')
-_CHROMIUM_BUILD_URL = global_config.global_config.get_config_value(
-    'NOTIFICATIONS', 'chromium_build_url', default='')
+CONFIG = global_config.global_config
+
+_SHERIFF_JS = CONFIG.get_config_value('NOTIFICATIONS', 'sheriffs', default='')
+_LAB_SHERIFF_JS = CONFIG.get_config_value(
+        'NOTIFICATIONS', 'lab_sheriffs', default='')
+_CHROMIUM_BUILD_URL = CONFIG.get_config_value(
+        'NOTIFICATIONS', 'chromium_build_url', default='')
 
 LAB_GOOD_STATES = ('open', 'throttled')
 
+ENABLE_DRONE_IN_RESTRICTED_SUBNET = CONFIG.get_config_value(
+        'CROS', 'enable_drone_in_restricted_subnet', type=bool,
+        default=False)
 
 class TestLabException(Exception):
     """Exception raised when the Test Lab blocks a test or suite."""
@@ -268,8 +272,7 @@
 
     @return: True if the Autotest instance is in lab.
     """
-    test_server_name = global_config.global_config.get_config_value(
-              'SERVER', 'hostname')
+    test_server_name = CONFIG.get_config_value('SERVER', 'hostname')
     return test_server_name.startswith('cautotest')
 
 
@@ -290,8 +293,7 @@
         return
 
     # Download the lab status from its home on the web.
-    status_url = global_config.global_config.get_config_value(
-            'CROS', 'lab_status_url')
+    status_url = CONFIG.get_config_value('CROS', 'lab_status_url')
     json_status = _get_lab_status(status_url)
     if json_status is None:
         # We go ahead and say the lab is open if we can't get the status.
@@ -439,15 +441,13 @@
 
     @return True, if shard_hostname is set, False otherwise.
     """
-    hostname = global_config.global_config.get_config_value(
-            'SHARD', 'shard_hostname', default=None)
+    hostname = CONFIG.get_config_value('SHARD', 'shard_hostname', default=None)
     return bool(hostname)
 
 
 def get_global_afe_hostname():
     """Read the hostname of the global AFE from the global configuration."""
-    return global_config.global_config.get_config_value(
-            'SERVER', 'global_afe_hostname')
+    return CONFIG.get_config_value('SERVER', 'global_afe_hostname')
 
 
 def is_restricted_user(username):
@@ -462,7 +462,7 @@
     if not username:
         return False
 
-    restricted_groups = global_config.global_config.get_config_value(
+    restricted_groups = CONFIG.get_config_value(
             'AUTOTEST_WEB', 'restricted_groups', default='').split(',')
     for group in restricted_groups:
         try:
@@ -694,8 +694,7 @@
         return None
     if os.path.isabs(creds_file):
         return creds_file
-    creds_dir = global_config.global_config.get_config_value(
-            'SERVER', 'creds_dir', default='')
+    creds_dir = CONFIG.get_config_value('SERVER', 'creds_dir', default='')
     if not creds_dir or not os.path.exists(creds_dir):
         creds_dir = common.autotest_dir
     return os.path.join(creds_dir, creds_file)