deploy_chrome: Always prompt to remove rootfs verification

This partially undoes a change for crbug.com/436971 in order
to make the behavior of deploy_chrome more consistent.

Developers using --target-dir will be prompted to remove rootfs
verification if necessary, allowing the root partition to be
modified, same as for developers not using --target-dir. This
allows simplification of documentation, e.g. for modifying
/etc/chrome_dev.conf.

Developers not wishing to remove rootfs verification and reboot
can answer 'No' to the prompt and deploy_chrome will still work
if --target-dir specifies a directory in /usr/local.

BUG=None
TEST=Run deploy_chrome --mount-dir=/opt/google/chrome
     --target-dir=/usr/local/chrome on a freshly imaged device
     and ensure that the prompt to remove rootfs verification
     is shown.

Change-Id: Ia174921eaff2ba91956c9886d58274e9a0d82c13
Reviewed-on: https://chromium-review.googlesource.com/1132417
Tested-by: Steven Bennetts <stevenjb@chromium.org>
Trybot-Ready: Steven Bennetts <stevenjb@chromium.org>
Reviewed-by: Robert Flack <flackr@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
diff --git a/scripts/deploy_chrome.py b/scripts/deploy_chrome.py
index babd460..8bec7de 100644
--- a/scripts/deploy_chrome.py
+++ b/scripts/deploy_chrome.py
@@ -100,7 +100,7 @@
       self.device = remote.RemoteDevice(options.to, port=options.port,
                                         ping=options.ping,
                                         private_key=options.private_key)
-    self._target_dir_is_still_readonly = multiprocessing.Event()
+    self._root_dir_is_still_readonly = multiprocessing.Event()
 
     self.copy_paths = chrome_util.GetCopyPaths('chrome')
     self.chrome_dir = _CHROME_DIR
@@ -146,12 +146,7 @@
       logging.info('Make sure the device is in developer mode!')
       logging.info('Skip this prompt by specifying --force.')
       if not cros_build_lib.BooleanPrompt('Remove roots verification?', False):
-        # Since we stopped Chrome earlier, it's good form to start it up again.
-        if self.options.startui:
-          logging.info('Starting Chrome...')
-          self.device.RunCommand('start ui')
-        raise DeployFailure('Need rootfs verification to be disabled. '
-                            'Aborting.')
+        return False
 
     logging.info('Removing rootfs verification from %s', self.options.to)
     # Running in VM's cause make_dev_ssd's firmware sanity checks to fail.
@@ -169,6 +164,8 @@
     # Make sure the rootfs is writable now.
     self._MountRootfsAsWritable(error_code_ok=False)
 
+    return True
+
   def _CheckUiJobStarted(self):
     # status output is in the format:
     # <job_name> <status> ['process' <pid>].
@@ -210,8 +207,8 @@
   def _MountRootfsAsWritable(self, error_code_ok=True):
     """Mounts the rootfs as writable.
 
-    If the command fails, and error_code_ok is True, and the target dir is not
-    writable then this function sets self._target_dir_is_still_readonly.
+    If the command fails and the root dir is not writable then this function
+    sets self._root_dir_is_still_readonly.
 
     Args:
       error_code_ok: See remote.RemoteAccess.RemoteSh for details.
@@ -220,9 +217,8 @@
     result = self.device.RunCommand(MOUNT_RW_COMMAND,
                                     error_code_ok=error_code_ok,
                                     capture_output=True)
-    if (result.returncode and
-        not self.device.IsDirWritable(self.options.target_dir)):
-      self._target_dir_is_still_readonly.set()
+    if result.returncode and not self.device.IsDirWritable('/'):
+      self._root_dir_is_still_readonly.set()
 
   def _EnsureTargetDir(self):
     """Ensures that the target directory exists on the remote device."""
@@ -364,10 +360,22 @@
                                     return_values=True)
     self._CheckDeviceFreeSpace(ret[0])
 
-    # If we're trying to deploy to a dir which is not writable and we failed
-    # to mark the rootfs as writable, try disabling rootfs verification.
-    if self._target_dir_is_still_readonly.is_set():
-      self._DisableRootfsVerification()
+    # If the root dir is not writable, try disabling rootfs verification.
+    # (We always do this by default so that developers can write to
+    # /etc/chriome_dev.conf and other directories in the rootfs).
+    if self._root_dir_is_still_readonly.is_set():
+      if self.options.noremove_rootfs_verification:
+        logging.warning('Skipping disable rootfs verification.')
+      elif not self._DisableRootfsVerification():
+        logging.warning('Failed to disable rootfs verification.')
+
+      # If the target dir is still not writable (i.e. the user opted out or the
+      # command failed), abort.
+      if not self.device.IsDirWritable(self.options.target_dir):
+        if self.options.startui:
+          logging.info('Restarting Chrome...')
+          self.device.RunCommand('start ui')
+        raise DeployFailure('Target location is not writable. Aborting.')
 
     if self.options.mount_dir is not None:
       self._MountTarget()
@@ -437,6 +445,8 @@
                            'it to the default mount directory.'
                            'Any existing mount on this directory will be '
                            'umounted first.')
+  parser.add_argument('--noremove-rootfs-verification', action='store_true',
+                      default=False, help='Never remove rootfs verification.')
 
   group = parser.add_argument_group('Advanced Options')
   group.add_argument('-l', '--local-pkg-path', type='path',