Set network's subnetwork.

When we're not using a default network, let's make sure we pick the
right subnetwork based on the region or raise an exception if one does
not exists..

Bug: 113535553
Test: acloud create with default and non-default network.
Change-Id: I8fba1ff1b0e2e8b8515d0b96aaf0e0e41b25bf20
diff --git a/create/create_args.py b/create/create_args.py
index cc939b5..45c119a 100644
--- a/create/create_args.py
+++ b/create/create_args.py
@@ -76,7 +76,7 @@
         dest="report_internal_ip",
         required=False,
         help="Report internal ip of the created instance instead of external "
-             "ip. Using the internal ip is valid when connecting from another "
+             "ip. Using the internal ip is used when connecting from another "
              "GCE instance.")
 
 
diff --git a/create/local_image_remote_instance.py b/create/local_image_remote_instance.py
index e608918..58625f1 100644
--- a/create/local_image_remote_instance.py
+++ b/create/local_image_remote_instance.py
@@ -241,7 +241,8 @@
             self.cvd_host_package_artifact)
         report = common_operations.CreateDevices(
             "create_cf", avd_spec.cfg, device_factory, avd_spec.num,
-            avd_spec.report_internal_ip, autoconnect=avd_spec.autoconnect)
+            report_internal_ip=avd_spec.report_internal_ip,
+            autoconnect=avd_spec.autoconnect)
         # Launch vnc client if we're auto-connecting.
         if avd_spec.autoconnect:
             for device in report.data.get("devices", []):
diff --git a/internal/lib/gcompute_client.py b/internal/lib/gcompute_client.py
index c645edc..cd30763 100755
--- a/internal/lib/gcompute_client.py
+++ b/internal/lib/gcompute_client.py
@@ -998,17 +998,19 @@
         api = self.service.regions().list(project=self._project)
         return self.Execute(api)
 
-    def _GetNetworkArgs(self, network):
+    def _GetNetworkArgs(self, network, zone):
         """Helper to generate network args that is used to create an instance.
 
         Args:
             network: A string, e.g. "default".
+            zone: String, representing zone name, e.g. "us-central1-f"
 
         Returns:
             A dictionary representing network args.
         """
         return {
             "network": self.GetNetworkUrl(network),
+            "subnetwork": self.GetSubnetworkUrl(network, zone),
             "accessConfigs": [{
                 "name": "External NAT",
                 "type": "ONE_TO_ONE_NAT"
@@ -1103,7 +1105,7 @@
         body = {
             "machineType": self.GetMachineType(machine_type, zone)["selfLink"],
             "name": instance,
-            "networkInterfaces": [self._GetNetworkArgs(network)],
+            "networkInterfaces": [self._GetNetworkArgs(network, zone)],
             "disks": disk_args,
             "serviceAccounts": [{
                 "email": "default",
@@ -1231,6 +1233,36 @@
         result = self.Execute(api)
         return result["selfLink"]
 
+    def GetSubnetworkUrl(self, network, zone):
+        """Get URL for a given network and zone.
+
+        Return the subnetwork for the network in the specified region that the
+        specified zone resides in. If there is no subnetwork for the specified
+        zone, raise an exception.
+
+        Args:
+            network: A string, representing network name, e.g "default"
+            zone: String, representing zone name, e.g. "us-central1-f"
+
+        Returns:
+            A URL that points to the network resource, e.g.
+            https://www.googleapis.com/compute/v1/projects/<project id>/
+            global/networks/default
+
+        Raises:
+            errors.NoSubnetwork: When no subnetwork exists for the zone
+            specified.
+        """
+        api = self.service.networks().get(
+            project=self._project, network=network)
+        result = self.Execute(api)
+        region = zone.rsplit("-", 1)[0]
+        for subnetwork in result["subnetworks"]:
+            if region in subnetwork:
+                return subnetwork
+        raise errors.NoSubnetwork("No subnetwork for network %s in region %s" %
+                                  (network, region))
+
     def CompareMachineSize(self, machine_type_1, machine_type_2, zone):
         """Compare the size of two machine types.
 
diff --git a/public/actions/create_cuttlefish_action.py b/public/actions/create_cuttlefish_action.py
index db48a43..b721211 100644
--- a/public/actions/create_cuttlefish_action.py
+++ b/public/actions/create_cuttlefish_action.py
@@ -155,6 +155,7 @@
         kernel_build_id = avd_spec.kernel_build_id
         num = avd_spec.num
         autoconnect = avd_spec.autoconnect
+        report_internal_ip = avd_spec.report_internal_ip
     logger.info(
         "Creating a cuttlefish device in project %s, build_target: %s, "
         "build_id: %s, num: %s, serial_log_file: %s, logcat_file: %s, "
diff --git a/public/errors.py b/public/errors.py
index 77ad0db..eb003f1 100755
--- a/public/errors.py
+++ b/public/errors.py
@@ -81,6 +81,10 @@
     """To catch device boot errors."""
 
 
+class NoSubnetwork(DriverError):
+    """When there is no subnetwork for the GCE."""
+
+
 class DeviceBootTimeoutError(DeviceBootError):
     """Raised when an AVD defice failed to boot within timeout."""