servo: Merge #15230 - Mach bootstrap: Improve and support more platforms (from UK992:mach-bootstrap); r=aneeshusa
authorUK992 <urbankrajnc92@gmail.com>
Sat, 04 Mar 2017 04:47:13 -0800
changeset 374961 ed2cad50092a85e7fc6cab021004b07d63c93052
parent 374960 97e94e028ed4d0cd64be28d1eb3cbf3106f051aa
child 374962 9c177d80ee844cb3c76b5c2e969ee260a8032eba
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaneeshusa
bugs15230
milestone54.0a1
servo: Merge #15230 - Mach bootstrap: Improve and support more platforms (from UK992:mach-bootstrap); r=aneeshusa <!-- Please describe your changes on the following line: --> r? @aneeshusa or @Wafflespeanut --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: d8a8e3e42eda3704d8793d398b24f2e37bded4ec
servo/python/servo/bootstrap.py
--- a/servo/python/servo/bootstrap.py
+++ b/servo/python/servo/bootstrap.py
@@ -5,31 +5,63 @@
 from __future__ import absolute_import, print_function
 
 from distutils.spawn import find_executable
 import json
 import os
 import platform
 import shutil
 import subprocess
+from subprocess import PIPE
 
 import servo.packages as packages
 from servo.util import extract, download_file, host_triple
 
 
+def run_as_root(command):
+    if os.geteuid() != 0:
+        command.insert(0, 'sudo')
+    return subprocess.call(command)
+
+
+def install_salt_dependencies(context, force):
+    install = False
+    if context.distro == 'Ubuntu':
+        pkgs = ['build-essential', 'libssl-dev', 'libffi-dev', 'python-dev']
+        command = ['apt-get', 'install']
+        if subprocess.call(['dpkg', '-s'] + pkgs, stdout=PIPE, stderr=PIPE) != 0:
+            install = True
+    elif context.distro in ['CentOS', 'CentOS Linux', 'Fedora']:
+        installed_pkgs = str(subprocess.check_output(['rpm', '-qa'])).replace('\n', '|')
+        pkgs = ['gcc', 'libffi-devel', 'python-devel', 'openssl-devel']
+        for p in pkgs:
+            command = ['dnf', 'install']
+            if "|{}".format(p) not in installed_pkgs:
+                install = True
+                break
+
+    if install:
+        if force:
+            command.append('-y')
+        print("Installing missing Salt dependencies...")
+        run_as_root(command + pkgs)
+
+
 def salt(context, force=False):
+    # Ensure Salt dependencies are installed
+    install_salt_dependencies(context, force)
     # Ensure Salt is installed in the virtualenv
     # It's not instaled globally because it's a large, non-required dependency,
     # and the installation fails on Windows
     print("Checking Salt installation...", end='')
     reqs_path = os.path.join(context.topdir, 'python', 'requirements-salt.txt')
     process = subprocess.Popen(
         ["pip", "install", "-q", "-I", "-r", reqs_path],
-        stdout=subprocess.PIPE,
-        stderr=subprocess.PIPE
+        stdout=PIPE,
+        stderr=PIPE
     )
     process.wait()
     if process.returncode:
         out, err = process.communicate()
         print('failed to install Salt via pip:')
         print('Output: {}\nError: {}'.format(out, err))
         return 1
     print("done")
@@ -81,17 +113,16 @@ def salt(context, force=False):
     if os.path.exists(pillar_dir):
         shutil.rmtree(pillar_dir)
     os.makedirs(pillar_dir, mode=0o700)
     for filename in pillar:
         with open(os.path.join(pillar_dir, filename), 'w') as pillar_file:
             pillar_file.write(json.dumps(pillar[filename]) + '\n')
 
     cmd = [
-        'sudo',
         # sudo escapes from the venv, need to use full path
         find_executable('salt-call'),
         '--local',
         '--config-dir={}'.format(config_dir),
         '--pillar-root={}'.format(pillar_dir),
         'state.apply',
         'servo-build-dependencies',
     ]
@@ -101,31 +132,31 @@ def salt(context, force=False):
         # Because `test=True` mode runs each state individually without
         # considering how required/previous states affect the system,
         # it will often report states with requisites as failing due
         # to the requisites not actually being run,
         # even though these are spurious and will succeed during
         # the actual highstate.
         # Hence `--retcode-passthrough` is not helpful in dry-run mode,
         # so only detect failures of the actual salt-call binary itself.
-        retcode = subprocess.call(cmd + ['test=True'])
+        retcode = run_as_root(cmd + ['test=True'])
         if retcode != 0:
             print('Something went wrong while bootstrapping')
             return retcode
 
         proceed = raw_input(
             'Proposed changes are above, proceed with bootstrap? [y/N]: '
         )
         if proceed.lower() not in ['y', 'yes']:
             return 0
 
         print('')
 
     print('Running Salt bootstrap')
-    retcode = subprocess.call(cmd + ['--retcode-passthrough'])
+    retcode = run_as_root(cmd + ['--retcode-passthrough'])
     if retcode == 0:
         print('Salt bootstrapping complete')
     else:
         print('Salt bootstrapping encountered errors')
     return retcode
 
 
 def windows_gnu(context, force=False):
@@ -214,16 +245,17 @@ def bootstrap(context, force=False):
     bootstrapper = None
 
     if "windows-gnu" in host_triple():
         bootstrapper = windows_gnu
     elif "windows-msvc" in host_triple():
         bootstrapper = windows_msvc
     elif "linux-gnu" in host_triple():
         distro, version, _ = platform.linux_distribution()
-        if distro == 'Ubuntu' and version == '14.04':
+        if distro in ['CentOS', 'CentOS Linux', 'Fedora', 'Ubuntu']:
+            context.distro = distro
             bootstrapper = salt
 
     if bootstrapper is None:
         print('Bootstrap support is not yet available for your OS.')
         return 1
 
     return bootstrapper(context, force=force)