Beispiel #1
0
def _get_jail_path(jail):
    '''
    .. versionadded:: 2016.3.4

    Return the jail's root directory (path) as shown in jls

    jail
        The jid or jail name
    '''
    jls = salt.utils.which('jls')
    if not jls:
        raise CommandNotFoundError('\'jls\' command not found')
    jails = __salt__['cmd.run_stdout']('{0} -n jid name path'.format(jls))
    for j in jails.splitlines():
        jid, jname, path = (x.split('=')[1].strip() for x in j.split())
        if jid == jail or jname == jail:
            return path.rstrip('/')
    # XΧΧ, TODO, not sure how to handle nonexistent jail
    return ''
Beispiel #2
0
def _get_jail_path(jail):
    """
    .. versionadded:: 2016.3.4

    Return the jail's root directory (path) as shown in jls

    jail
        The jid or jail name
    """
    jls = salt.utils.path.which("jls")
    if not jls:
        raise CommandNotFoundError("'jls' command not found")
    jails = __salt__["cmd.run_stdout"]("{} -n jid name path".format(jls))
    for j in jails.splitlines():
        jid, jname, path = (x.split("=")[1].strip() for x in j.split())
        if jid == jail or jname == jail:
            return path.rstrip("/")
    # XΧΧ, TODO, not sure how to handle nonexistent jail
    return ""
Beispiel #3
0
def is_fuse_exec(cmd):
    '''
    Returns true if the command passed is a fuse mountable application.

    CLI Example:

    .. code-block:: bash

        salt '*' mount.is_fuse_exec sshfs
    '''
    cmd_path = _which(cmd)

    # No point in running ldd on a command that doesn't exist
    if not cmd_path:
        return False
    elif not _which('ldd'):
        raise CommandNotFoundError('ldd')

    out = __salt__['cmd.run']('ldd {0}'.format(cmd_path), python_shell=False)
    return 'libfuse' in out
Beispiel #4
0
def version(bin_env=None):
    '''
    .. versionadded:: 0.17.0

    Returns the version of pip. Use ``bin_env`` to specify the path to a
    virtualenv and get the version of pip in that virtualenv.

    If unable to detect the pip version, returns ``None``.

    CLI Example:

    .. code-block:: bash

        salt '*' pip.version
    '''
    contextkey = 'pip.version'
    if bin_env is not None:
        contextkey = '{0}.{1}'.format(contextkey, bin_env)

    if contextkey in __context__:
        return __context__[contextkey]

    cmd = _get_pip_bin(bin_env)[:]
    cmd.append('--version')

    ret = __salt__['cmd.run_all'](cmd, python_shell=False)
    if ret['retcode']:
        raise CommandNotFoundError('Could not find a `pip` binary')

    try:
        pip_version = re.match(r'^pip (\S+)', ret['stdout']).group(1)
    except AttributeError:
        pip_version = None

    __context__[contextkey] = pip_version
    return pip_version
Beispiel #5
0
def bootstrap(force=False):
    '''
    Download and install the latest version of the Chocolatey package manager
    via the official bootstrap.

    Chocolatey requires Windows PowerShell and the .NET v4.0 runtime. Depending
    on the host's version of Windows, chocolatey.bootstrap will attempt to
    ensure these prerequisites are met by downloading and executing the
    appropriate installers from Microsoft.

    Note that if PowerShell is installed, you may have to restart the host
    machine for Chocolatey to work.

    force
        Run the bootstrap process even if Chocolatey is found in the path.

    CLI Example:

    .. code-block:: bash

        salt '*' chocolatey.bootstrap
        salt '*' chocolatey.bootstrap force=True
    '''
    # Check if Chocolatey is already present in the path
    try:
        choc_path = _find_chocolatey(__context__, __salt__)
    except CommandExecutionError:
        choc_path = None
    if choc_path and not force:
        return 'Chocolatey found at {0}'.format(choc_path)

    # The following lookup tables are required to determine the correct
    # download required to install PowerShell. That's right, there's more
    # than one! You're welcome.
    ps_downloads = {
        ('Vista', 'x86'):
        'http://download.microsoft.com/download/A/7/5/A75BC017-63CE-47D6-8FA4-AFB5C21BAC54/Windows6.0-KB968930-x86.msu',
        ('Vista', 'AMD64'):
        'http://download.microsoft.com/download/3/C/8/3C8CF51E-1D9D-4DAA-AAEA-5C48D1CD055C/Windows6.0-KB968930-x64.msu',
        ('2008Server', 'x86'):
        'http://download.microsoft.com/download/F/9/E/F9EF6ACB-2BA8-4845-9C10-85FC4A69B207/Windows6.0-KB968930-x86.msu',
        ('2008Server', 'AMD64'):
        'http://download.microsoft.com/download/2/8/6/28686477-3242-4E96-9009-30B16BED89AF/Windows6.0-KB968930-x64.msu'
    }

    # It took until .NET v4.0 for Microsoft got the hang of making installers,
    # this should work under any version of Windows
    net4_url = 'http://download.microsoft.com/download/1/B/E/1BE39E79-7E39-46A3-96FF-047F95396215/dotNetFx40_Full_setup.exe'

    temp_dir = tempfile.gettempdir()

    # Check if PowerShell is installed. This should be the case for every
    # Windows release following Server 2008.
    ps_path = 'C:\\Windows\\SYSTEM32\\WindowsPowerShell\\v1.0\\powershell.exe'

    if not __salt__['cmd.has_exec'](ps_path):
        if (__grains__['osrelease'], __grains__['cpuarch']) in ps_downloads:
            # Install the appropriate release of PowerShell v2.0
            url = ps_downloads[(__grains__['osrelease'],
                                __grains__['cpuarch'])]
            dest = os.path.join(temp_dir, 'powershell.exe')
            __salt__['cp.get_url'](url, dest)
            cmd = [dest, '/quiet', '/norestart']
            result = __salt__['cmd.run_all'](cmd, python_shell=False)
            if result['retcode'] != 0:
                err = ('Installing Windows PowerShell failed. Please run the '
                       'installer GUI on the host to get a more specific '
                       'reason.')
                log.error(err)
                raise CommandExecutionError(err)
        else:
            err = 'Windows PowerShell not found'
            log.error(err)
            raise CommandNotFoundError(err)

    # Run the .NET Framework 4 web installer
    dest = os.path.join(temp_dir, 'dotnet4.exe')
    __salt__['cp.get_url'](net4_url, dest)
    cmd = [dest, '/q', '/norestart']
    result = __salt__['cmd.run_all'](cmd, python_shell=False)
    if result['retcode'] != 0:
        err = ('Installing .NET v4.0 failed. Please run the installer GUI on '
               'the host to get a more specific reason.')
        log.error(err)
        raise CommandExecutionError(err)

    # Run the Chocolatey bootstrap.
    cmd = ('{0} -NoProfile -ExecutionPolicy unrestricted '
           '-Command "iex ((new-object net.webclient).'
           'DownloadString(\'https://chocolatey.org/install.ps1\'))" '
           '&& SET PATH=%PATH%;%systemdrive%\\chocolatey\\bin'.format(ps_path))
    result = __salt__['cmd.run_all'](cmd, python_shell=True)

    if result['retcode'] != 0:
        err = 'Bootstrapping Chocolatey failed: {0}'.format(result['stderr'])
        log.error(err)
        raise CommandExecutionError(err)

    return result['stdout']
Beispiel #6
0
 def wrapped(*args, **kwargs):
     if salt.utils.which(exe) is None:
         raise CommandNotFoundError(
             'The \'{0}\' binary was not found in $PATH.'.format(exe))
     return function(*args, **kwargs)
Beispiel #7
0
def bootstrap(force=False, source=None):
    """
    Download and install the latest version of the Chocolatey package manager
    via the official bootstrap.

    Chocolatey requires Windows PowerShell and the .NET v4.0 runtime. Depending
    on the host's version of Windows, chocolatey.bootstrap will attempt to
    ensure these prerequisites are met by downloading and executing the
    appropriate installers from Microsoft.

    .. note::
        If PowerShell is installed, you may have to restart the host machine for
        Chocolatey to work.

    .. note::
        If you're installing offline using the source parameter, the PowerShell
        and .NET requirements must already be met on the target. This shouldn't
        be a problem on Windows versions 2012/8 and later

    Args:

        force (bool):
            Run the bootstrap process even if Chocolatey is found in the path.

        source (str):
            The location of the ``.nupkg`` file or ``.ps1`` file to run from an
            alternate location. This can be one of the following types of URLs:

            - salt://
            - http(s)://
            - ftp://
            - file:// - A local file on the system

            .. versionadded:: 3001

    Returns:
        str: The stdout of the Chocolatey installation script

    CLI Example:

    .. code-block:: bash

        # To bootstrap Chocolatey
        salt '*' chocolatey.bootstrap
        salt '*' chocolatey.bootstrap force=True

        # To bootstrap Chocolatey offline from a file on the salt master
        salt '*' chocolatey.bootstrap source=salt://files/chocolatey.nupkg

        # To bootstrap Chocolatey from a file on C:\\Temp
        salt '*' chocolatey.bootstrap source=C:\\Temp\\chocolatey.nupkg
    """
    # Check if Chocolatey is already present in the path
    try:
        choc_path = _find_chocolatey()
    except CommandExecutionError:
        choc_path = None
    if choc_path and not force:
        return "Chocolatey found at {}".format(choc_path)

    temp_dir = tempfile.gettempdir()

    # Make sure PowerShell is on the System if we're passing source
    # Vista and Windows Server 2008 do not have Powershell installed
    powershell_info = __salt__["cmd.shell_info"](shell="powershell")
    if not powershell_info["installed"]:
        # The following lookup tables are required to determine the correct
        # download required to install PowerShell. That's right, there's more
        # than one! You're welcome.
        ps_downloads = {
            (
                "Vista",
                "x86",
            ):
            "http://download.microsoft.com/download/A/7/5/A75BC017-63CE-47D6-8FA4-AFB5C21BAC54/Windows6.0-KB968930-x86.msu",
            (
                "Vista",
                "AMD64",
            ):
            "http://download.microsoft.com/download/3/C/8/3C8CF51E-1D9D-4DAA-AAEA-5C48D1CD055C/Windows6.0-KB968930-x64.msu",
            (
                "2008Server",
                "x86",
            ):
            "http://download.microsoft.com/download/F/9/E/F9EF6ACB-2BA8-4845-9C10-85FC4A69B207/Windows6.0-KB968930-x86.msu",
            (
                "2008Server",
                "AMD64",
            ):
            "http://download.microsoft.com/download/2/8/6/28686477-3242-4E96-9009-30B16BED89AF/Windows6.0-KB968930-x64.msu",
        }

        # PowerShell needs to be installed on older systems (Vista, 2008Server)
        if (__grains__["osrelease"], __grains__["cpuarch"]) in ps_downloads:

            # Install the appropriate release of PowerShell v2.0
            url = ps_downloads[(__grains__["osrelease"],
                                __grains__["cpuarch"])]
            dest = os.path.join(temp_dir, os.path.basename(url))
            # Download the KB
            try:
                log.debug("Downloading PowerShell...")
                __salt__["cp.get_url"](path=url, dest=dest)
            except MinionError:
                err = "Failed to download PowerShell KB for {}".format(
                    __grains__["osrelease"])
                if source:
                    raise CommandExecutionError(
                        "{}: PowerShell is required to bootstrap Chocolatey "
                        "with Source".format(err))
                raise CommandExecutionError(err)
            # Install the KB
            cmd = [dest, "/quiet", "/norestart"]
            log.debug("Installing PowerShell...")
            result = __salt__["cmd.run_all"](cmd, python_shell=False)
            if result["retcode"] != 0:
                err = ("Failed to install PowerShell KB. For more information "
                       "run the installer manually on the host")
                raise CommandExecutionError(err)
        else:
            err = "Windows PowerShell Installation not available"
            raise CommandNotFoundError(err)

    # Check that .NET v4.0+ is installed
    # Windows 7 / Windows Server 2008 R2 and below do not come with at least
    # .NET v4.0 installed
    if not __utils__["dotnet.version_at_least"](version="4"):
        # It took until .NET v4.0 for Microsoft got the hang of making
        # installers, this should work under any version of Windows
        url = "http://download.microsoft.com/download/1/B/E/1BE39E79-7E39-46A3-96FF-047F95396215/dotNetFx40_Full_setup.exe"
        dest = os.path.join(temp_dir, os.path.basename(url))
        # Download the .NET Framework 4 web installer
        try:
            log.debug("Downloading .NET v4.0...")
            __salt__["cp.get_url"](path=url, dest=dest)
        except MinionError:
            err = "Failed to download .NET v4.0 Web Installer"
            if source:
                err = ("{}: .NET v4.0+ is required to bootstrap "
                       "Chocolatey with Source".format(err))
            raise CommandExecutionError(err)

        # Run the .NET Framework 4 web installer
        cmd = [dest, "/q", "/norestart"]
        log.debug("Installing .NET v4.0...")
        result = __salt__["cmd.run_all"](cmd, python_shell=False)
        if result["retcode"] != 0:
            err = ("Failed to install .NET v4.0 failed. For more information "
                   "run the installer manually on the host")
            raise CommandExecutionError(err)

    # Define target / destination
    if source:
        url = source
    else:
        url = "https://chocolatey.org/install.ps1"
    dest = os.path.join(temp_dir, os.path.basename(url))

    # Download Chocolatey installer
    try:
        log.debug("Downloading Chocolatey: %s", os.path.basename(url))
        script = __salt__["cp.get_url"](path=url, dest=dest)
        log.debug("Script: %s", script)
    except MinionError:
        err = "Failed to download Chocolatey Installer"
        if source:
            err = "{0} from source"
        raise CommandExecutionError(err)

    # If this is a nupkg download we need to unzip it first
    if os.path.splitext(os.path.basename(dest))[1] == ".nupkg":
        log.debug("Unzipping Chocolatey: %s", dest)
        __salt__["archive.unzip"](
            zip_file=dest,
            dest=os.path.join(os.path.dirname(dest), "chocolatey"),
            extract_perms=False,
        )
        script = os.path.join(os.path.dirname(dest), "chocolatey", "tools",
                              "chocolateyInstall.ps1")

    if not os.path.exists(script):
        raise CommandExecutionError(
            "Failed to find Chocolatey installation script: {}".format(script))

    # Run the Chocolatey bootstrap
    log.debug("Installing Chocolatey: %s", script)
    result = __salt__["cmd.script"](script,
                                    cwd=os.path.dirname(script),
                                    shell="powershell",
                                    python_shell=True)
    if result["retcode"] != 0:
        err = "Bootstrapping Chocolatey failed: {}".format(result["stderr"])
        raise CommandExecutionError(err)

    return result["stdout"]
Beispiel #8
0
def _run_composer(
    action,
    directory=None,
    composer=None,
    php=None,
    runas=None,
    prefer_source=None,
    prefer_dist=None,
    no_scripts=None,
    no_plugins=None,
    optimize=None,
    no_dev=None,
    quiet=False,
    composer_home="/root",
    extra_flags=None,
    env=None,
):
    """
    Run PHP's composer with a specific action.

    If composer has not been installed globally making it available in the
    system PATH & making it executable, the ``composer`` and ``php`` parameters
    will need to be set to the location of the executables.

    action
        The action to pass to composer ('install', 'update', 'selfupdate', etc).

    directory
        Directory location of the composer.json file.  Required except when
        action='selfupdate'

    composer
        Location of the composer.phar file. If not set composer will
        just execute "composer" as if it is installed globally.
        (i.e. /path/to/composer.phar)

    php
        Location of the php executable to use with composer.
        (i.e. /usr/bin/php)

    runas
        Which system user to run composer as.

    prefer_source
        --prefer-source option of composer.

    prefer_dist
        --prefer-dist option of composer.

    no_scripts
        --no-scripts option of composer.

    no_plugins
        --no-plugins option of composer.

    optimize
        --optimize-autoloader option of composer. Recommended for production.

    no_dev
        --no-dev option for composer. Recommended for production.

    quiet
        --quiet option for composer. Whether or not to return output from composer.

    composer_home
        $COMPOSER_HOME environment variable

    extra_flags
        None, or a string containing extra flags to pass to composer.

    env
        A list of environment variables to be set prior to execution.
    """
    if composer is not None:
        if php is None:
            php = "php"
    else:
        composer = "composer"

    # Validate Composer is there
    if not _valid_composer(composer):
        raise CommandNotFoundError(
            "'composer.{}' is not available. Couldn't find '{}'.".format(
                action, composer))

    if action is None:
        raise SaltInvocationError("The 'action' argument is required")

    # Don't need a dir for the 'selfupdate' action; all other actions do need a dir
    if directory is None and action != "selfupdate":
        raise SaltInvocationError(
            "The 'directory' argument is required for composer.{}".format(
                action))

    # Base Settings
    cmd = [composer, action, "--no-interaction", "--no-ansi"]

    if extra_flags is not None:
        cmd.extend(salt.utils.args.shlex_split(extra_flags))

    # If php is set, prepend it
    if php is not None:
        cmd = [php] + cmd

    # Add Working Dir
    if directory is not None:
        cmd.extend(["--working-dir", directory])

    # Other Settings
    if quiet is True:
        cmd.append("--quiet")

    if no_dev is True:
        cmd.append("--no-dev")

    if prefer_source is True:
        cmd.append("--prefer-source")

    if prefer_dist is True:
        cmd.append("--prefer-dist")

    if no_scripts is True:
        cmd.append("--no-scripts")

    if no_plugins is True:
        cmd.append("--no-plugins")

    if optimize is True:
        cmd.append("--optimize-autoloader")

    if env is not None:
        env = salt.utils.data.repack_dictlist(env)
        env["COMPOSER_HOME"] = composer_home
    else:
        env = {"COMPOSER_HOME": composer_home}

    result = __salt__["cmd.run_all"](cmd,
                                     runas=runas,
                                     env=env,
                                     python_shell=False)

    if result["retcode"] != 0:
        raise CommandExecutionError(result["stderr"])

    if quiet is True:
        return True

    return result
Beispiel #9
0
 def wrapped(*args, **kwargs):
     if salt.utils.which_bin(exes) is None:
         raise CommandNotFoundError(
             'None of provided binaries({0}) was not found '
             'in $PATH.'.format(['{0!r}'.format(exe) for exe in exes]))
     return function(*args, **kwargs)
Beispiel #10
0
 def wrapped(*args, **kwargs):
     if salt.utils.path.which_bin(exes) is None:
         raise CommandNotFoundError(
             "None of provided binaries({}) was not found "
             "in $PATH.".format(["'{}'".format(exe) for exe in exes]))
     return function(*args, **kwargs)
Beispiel #11
0
 def wrapped(*args, **kwargs):
     if salt.utils.path.which(exe) is None:
         raise CommandNotFoundError(
             "The '{}' binary was not found in $PATH.".format(exe))
     return function(*args, **kwargs)
Beispiel #12
0
def _get_pip_bin(bin_env):
    '''
    Locate the pip binary, either from `bin_env` as a virtualenv, as the
    executable itself, or from searching conventional filesystem locations
    '''
    if not bin_env:
        logger.debug('pip: Using pip from currently-running Python')
        return [os.path.normpath(sys.executable), '-m', 'pip']

    python_bin = 'python.exe' if salt.utils.platform.is_windows() else 'python'

    def _search_paths(*basedirs):
        ret = []
        for path in basedirs:
            ret.extend([
                os.path.join(path, python_bin),
                os.path.join(path, 'bin', python_bin),
                os.path.join(path, 'Scripts', python_bin)
            ])
        return ret

    # try to get python bin from virtualenv (i.e. bin_env)
    if os.path.isdir(bin_env):
        for bin_path in _search_paths(bin_env):
            if os.path.isfile(bin_path):
                if os.access(bin_path, os.X_OK):
                    logger.debug('pip: Found python binary: %s', bin_path)
                    return [os.path.normpath(bin_path), '-m', 'pip']
                else:
                    logger.debug(
                        'pip: Found python binary by name but it is not '
                        'executable: %s', bin_path)
        raise CommandNotFoundError(
            'Could not find a pip binary in virtualenv {0}'.format(bin_env))

    # bin_env is the python or pip binary
    elif os.access(bin_env, os.X_OK):
        if os.path.isfile(bin_env):
            # If the python binary was passed, return it
            if 'python' in os.path.basename(bin_env):
                return [os.path.normpath(bin_env), '-m', 'pip']
            # Try to find the python binary based on the location of pip in a
            # virtual environment, should be relative
            if 'pip' in os.path.basename(bin_env):
                # Look in the same directory as the pip binary, and also its
                # parent directories.
                pip_dirname = os.path.dirname(bin_env)
                pip_parent_dir = os.path.dirname(pip_dirname)
                for bin_path in _search_paths(pip_dirname, pip_parent_dir):
                    if os.path.isfile(bin_path):
                        logger.debug('pip: Found python binary: %s', bin_path)
                        return [os.path.normpath(bin_path), '-m', 'pip']

            # Couldn't find python, use the passed pip binary
            # This has the limitation of being unable to update pip itself
            return [os.path.normpath(bin_env)]

        raise CommandExecutionError(
            'Could not find a pip binary within {0}'.format(bin_env))
    else:
        raise CommandNotFoundError(
            'Access denied to {0}, could not find a pip binary'.format(
                bin_env))
Beispiel #13
0
def _run_composer(action,
                  directory=None,
                  composer=None,
                  php=None,
                  runas=None,
                  prefer_source=None,
                  prefer_dist=None,
                  no_scripts=None,
                  no_plugins=None,
                  optimize=None,
                  no_dev=None,
                  quiet=False,
                  composer_home='/root',
                  extra_flags=None):
    '''
    Run PHP's composer with a specific action.

    If composer has not been installed globally making it available in the
    system PATH & making it executable, the ``composer`` and ``php`` parameters
    will need to be set to the location of the executables.

    action
        The action to pass to composer ('install', 'update', 'selfupdate', etc).

    directory
        Directory location of the composer.json file.  Required except when
        action='selfupdate'

    composer
        Location of the composer.phar file. If not set composer will
        just execute "composer" as if it is installed globally.
        (i.e. /path/to/composer.phar)

    php
        Location of the php executable to use with composer.
        (i.e. /usr/bin/php)

    runas
        Which system user to run composer as.

    prefer_source
        --prefer-source option of composer.

    prefer_dist
        --prefer-dist option of composer.

    no_scripts
        --no-scripts option of composer.

    no_plugins
        --no-plugins option of composer.

    optimize
        --optimize-autoloader option of composer. Recommended for production.

    no_dev
        --no-dev option for composer. Recommended for production.

    quiet
        --quiet option for composer. Whether or not to return output from composer.

    composer_home
        $COMPOSER_HOME environment variable

    extra_flags
        None, or a string containing extra flags to pass to composer.
    '''
    if composer is not None:
        if php is None:
            php = 'php'
    else:
        composer = 'composer'

    # Validate Composer is there
    if not _valid_composer(composer):
        raise CommandNotFoundError(
            '\'composer.{0}\' is not available. Couldn\'t find \'{1}\'.'.
            format(action, composer))

    if action is None:
        raise SaltInvocationError('The \'action\' argument is required')

    # Don't need a dir for the 'selfupdate' action; all other actions do need a dir
    if directory is None and action != 'selfupdate':
        raise SaltInvocationError(
            'The \'directory\' argument is required for composer.{0}'.format(
                action))

    # Base Settings
    cmd = [composer, action, '--no-interaction', '--no-ansi']

    if extra_flags is not None:
        cmd.extend(shlex.split(extra_flags))

    # If php is set, prepend it
    if php is not None:
        cmd = [php] + cmd

    # Add Working Dir
    if directory is not None:
        cmd.extend(['--working-dir', directory])

    # Other Settings
    if quiet is True:
        cmd.append('--quiet')

    if no_dev is True:
        cmd.append('--no-dev')

    if prefer_source is True:
        cmd.append('--prefer-source')

    if prefer_dist is True:
        cmd.append('--prefer-dist')

    if no_scripts is True:
        cmd.append('--no-scripts')

    if no_plugins is True:
        cmd.append('--no-plugins')

    if optimize is True:
        cmd.append('--optimize-autoloader')

    result = __salt__['cmd.run_all'](cmd,
                                     runas=runas,
                                     env={
                                         'COMPOSER_HOME': composer_home
                                     },
                                     python_shell=False)

    if result['retcode'] != 0:
        raise CommandExecutionError(result['stderr'])

    if quiet is True:
        return True

    return result