cros deploy: save/restore selinux per-run, not per-pkg

If we're deploying multiple packages, we don't need to toggle the
SELinux state for every package we install, just for the overall
run.  This required 3x ssh calls per-package, but now it's 3 total.

BUG=None
TEST=`cros deploy` with multiple packages still saves & restores selinux state

Change-Id: Id84bb2a5da092dfb5b1a2a622fdcbdd06d71cdce
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/2651160
Commit-Queue: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Qijiang Fan <fqj@google.com>
diff --git a/cli/deploy.py b/cli/deploy.py
index db23edb..1cac9df 100644
--- a/cli/deploy.py
+++ b/cli/deploy.py
@@ -873,9 +873,6 @@
     pkgpath: path to tarball
     root: Package installation root path.
   """
-  enforced = device.IsSELinuxEnforced()
-  if enforced:
-    device.run(['setenforce', '0'])
   pkgroot = os.path.join(device.work_dir, 'packages')
   pkg_dirname = os.path.basename(os.path.dirname(pkgpath))
   pkgpath_device = os.path.join(pkgroot, pkg_dirname, os.path.basename(pkgpath))
@@ -885,8 +882,6 @@
        'tar', 'tf', pkgpath_device, '|',
        'restorecon', '-i', '-f', '-'],
       remote_sudo=True)
-  if enforced:
-    device.run(['setenforce', '1'])
 
 
 def _GetPackagesByCPV(cpvs, strip, sysroot):
@@ -983,6 +978,13 @@
 
 def _EmergePackages(pkgs, device, strip, sysroot, root, board, emerge_args):
   """Call _Emerge for each package in pkgs."""
+  if device.IsSELinuxAvailable():
+    enforced = device.IsSELinuxEnforced()
+    if enforced:
+      device.run(['setenforce', '0'])
+  else:
+    enforced = False
+
   dlc_deployed = False
   # This message is read by BrilloDeployOperation.
   logging.info('Preparing local packages for transfer.')
@@ -1003,6 +1005,9 @@
                   '--ignore-fail-on-non-empty', '/build/rootfs', '/build'],
                  check=False)
 
+  if enforced:
+    device.run(['setenforce', '1'])
+
   # Restart dlcservice so it picks up the newly installed DLC modules (in case
   # we installed new DLC images).
   if dlc_deployed:
diff --git a/cli/deploy_unittest.py b/cli/deploy_unittest.py
index c8b7668..353d2ae 100644
--- a/cli/deploy_unittest.py
+++ b/cli/deploy_unittest.py
@@ -373,11 +373,9 @@
 
     def GetRestoreconCommand(pkgfile):
       remote_path = os.path.join('/testdir/packages/to/', pkgfile)
-      return [['setenforce', '0'],
-              ['cd', '/', '&&',
+      return [['cd', '/', '&&',
                'tar', 'tf', remote_path, '|',
-               'restorecon', '-i', '-f', '-'],
-              ['setenforce', '1']]
+               'restorecon', '-i', '-f', '-']]
 
     self.device.device.selinux_available = True
     packages = ['some/foo-1.2.3', _BINPKG, 'some/foobar-2.0']
@@ -398,9 +396,11 @@
     self.assertEqual(self.unmerge.call_count, 0)
 
     self.assertEqual(self.device.device.cmds,
+                     [['setenforce', '0']] +
                      GetRestoreconCommand('foo-1.2.3.tbz2') +
                      GetRestoreconCommand('bar-1.2.5.tbz2') +
-                     GetRestoreconCommand('foobar-2.0.tbz2'))
+                     GetRestoreconCommand('foobar-2.0.tbz2') +
+                     [['setenforce', '1']])
 
   def testDeployUnmerge(self):
     """Test that deploy._Unmerge is called for each package."""