コード例 #1
0
    def _process_hook(self, hook, shelf):
        try:
            new_data = self._retrieve_path_data(hook.path)
        except InFlightStatusError:
            return

        old_data = shelf.get(hook.name + "|" + hook.path, None)

        if 'post.add' in hook.triggers and not old_data and new_data:
            log.info("Previous state not found; action for %s will be run",
                     hook.name)
        elif 'post.remove' in hook.triggers and old_data and not new_data:
            log.info('Path %s was removed; action for %s will be run',
                     hook.path, hook.name)
        elif 'post.update' in hook.triggers and old_data and new_data and old_data != new_data:
            log.info(
                "Data has changed from previous state; action for %s will be run",
                hook.name)
        else:
            log.debug("No change in path %s for hook %s", hook.path, hook.name)
            shelf[hook.name + '|' + hook.path] = new_data
            return

        log.info("Running action for %s", hook.name)
        action_env = dict(os.environ)
        env_key = self._retrieve_env_key(hook.path)
        if old_data:
            action_env['CFN_OLD_%s' % env_key] = self._as_string(old_data)
        if new_data:
            action_env['CFN_NEW_%s' % env_key] = self._as_string(new_data)

        action = hook.action
        if hook.runas:
            action = ['su', hook.runas, '-c', action]

        result = ProcessHelper(action, env=action_env).call()

        if result.returncode:
            log.warn(
                "Action for %s exited with %s; will retry on next iteration",
                hook.name, result.returncode)
        else:
            shelf[hook.name + '|' + hook.path] = new_data
        log.debug("Action for %s output: %s", hook.name,
                  result.stdout if result.stdout else '<None>')
コード例 #2
0
    def _gem_is_installed(self, pkg, ver=None):
        """"
        Check to see if a package at version ver is installed.
        If ver is not specified, just check for the package.
        """
        log.debug("Checking to see if %s-%s is already installed", pkg, ver)

        queryCmd = ['gem', 'query', '-i', '-n', '^%s$' % pkg]

        if ver:
            queryCmd.extend(['-v', '%s' % ver])

        result = ProcessHelper(queryCmd).call()

        if result.returncode:
            return False
        else:
            return True
コード例 #3
0
    def set_service_enabled(self, service, enabled=True):
        if not os.path.exists(self._executable):
            raise ToolError("Cannot find update-rc.d")

        result = ProcessHelper(
            [self._executable, service,
             'enable' if enabled else 'disable']).call()

        if result.returncode:
            log.error("update-rc.d failed with error %s. Output: %s",
                      result.returncode, result.stdout)
            raise ToolError(
                "Could not %s service %s" %
                ("enable" if enabled else "disable", service),
                result.returncode)
        else:
            log.info("%s service %s", "enabled" if enabled else "disabled",
                     service)
コード例 #4
0
ファイル: apt_tool.py プロジェクト: tdfacer/aws-cfn-bootstrap
    def _pkg_installed(self, pkg, pkg_name):
        """
        Test if a package is installed (exact version match if version is specified), returning a boolean.

        Arguments:
        pkg -- the full package specification (including version if specified) in pkg=version format
        pkg_name -- the name of the package
        """

        result = ProcessHelper(['dpkg-query', '-f', '${Status}|${Package}=${Version}', '-W', pkg_name], stderr=subprocess.PIPE).call()

        if result.returncode or not result.stdout:
            return False

        status,divider,spec = result.stdout.strip().partition('|')

        if status.rpartition(" ")[2] != 'installed':
            return False

        return spec.startswith(pkg)
コード例 #5
0
    def apply(self, action, auth_config=None):
        """
        Install a set of packages via easy_install, returning the packages actually installed or updated.

        Arguments:
        action -- a dict of package name to version; version can be empty, a single string or a list of strings

        Exceptions:
        ToolError -- on expected failures (such as a non-zero exit code)
        """

        pkgs_changed = []

        if not action.keys():
            log.debug("No packages specified for python")
            return pkgs_changed

        pkgs = []

        for pkg in action:
            if not action[pkg] or isinstance(action[pkg], basestring):
                pkgs.append(PythonTool._pkg_spec(pkg, action[pkg]))
            else:
                pkgs.extend(
                    PythonTool._pkg_spec(pkg, ver) for ver in action[pkg])

            pkgs_changed.append(pkg)

        log.info("Attempting to install %s via easy_install", pkgs)

        result = ProcessHelper(['easy_install'] + pkgs).call()

        if result.returncode:
            log.error("easy_install failed. Output: %s", result.stdout)
            raise ToolError("Could not successfully install python packages",
                            result.returncode)
        else:
            log.info("easy_install installed %s", pkgs)
            log.debug("easy_install output: %s", result.stdout)

        return pkgs_changed
コード例 #6
0
ファイル: posix_security.py プロジェクト: zhaohc10/airflow2
def _modify_user(user_name, groups=[], homedir=None):
    """ Modify a user and return True, else return False """
    if not homedir and not groups:
        log.info("No homedir or groups specified; not modifying %s", user_name)
        return False

    cmd = ['/usr/sbin/usermod']

    if groups:
        gids = _get_gids(groups)
        current_gids = _gids_for_user(user_name)
        if frozenset(gids) ^ frozenset(current_gids):
            cmd.extend(['-G', ','.join(gids)])
        else:
            log.debug("Groups have not changed for %s", user_name)

    if homedir:
        if homedir != _get_user_homedir(user_name):
            cmd.extend(['-d', homedir])
        else:
            log.debug("Homedir has not changed for %s", user_name)

    if len(cmd) == 1:
        log.debug("User %s does not need modification", user_name)
        return False

    cmd.append(user_name)

    result = ProcessHelper(cmd).call()

    if result.returncode:
        log.error("Failed to modify user %s", user_name)
        log.debug("Usermod output: %s", result.stdout)
        raise ToolError("Failed to modify user %s" % user_name)
    else:
        log.info("Modified user %s successfully", user_name)
        return True
コード例 #7
0
ファイル: posix_security.py プロジェクト: zhaohc10/airflow2
def _create_user(user_name, groups=[], homedir=None, uid=None):
    gids = _get_gids(groups)

    cmd = ['/usr/sbin/useradd', '-M', '-r', '--shell', '/sbin/nologin']

    if homedir:
        cmd.extend(['-d', homedir])

    if uid:
        cmd.extend(['-u', uid])

    if gids:
        cmd.extend(['-G', ','.join(gids)])

    cmd.append(user_name)

    result = ProcessHelper(cmd).call()

    if result.returncode:
        log.error("Failed to add user %s", user_name)
        log.debug("Useradd output: %s", result.stdout)
        raise ToolError("Failed to add user %s" % user_name)
    else:
        log.info("Added user %s successfully", user_name)
コード例 #8
0
ファイル: apt_tool.py プロジェクト: tdfacer/aws-cfn-bootstrap
    def _pkg_available(self, pkg):
        result = ProcessHelper(['apt-cache', '-q', 'show', pkg]).call()

        return result.returncode == 0
コード例 #9
0
ファイル: command_tool.py プロジェクト: zhaohc10/airflow2
    def apply(self, action):
        """
        Execute a set of commands, returning a list of commands that were executed.

        Arguments:
        action -- a dict of command to attributes, where attributes has keys of:
            command: the command to run (a string or list)
            cwd: working directory (a string)
            env: a dictionary of environment variables
            test: a commmand to run; if it returns zero, the command will run
            ignoreErrors: if true, ignore errors
            waitAfterCompletion: # of seconds to wait after completion (or "forever")
            defaults: a command to run; the stdout will be used to provide defaults

        Exceptions:
        ToolError -- on expected failures
        """

        commands_run = []

        if not action:
            log.debug("No commands specified")
            return commands_run

        for name in sorted(action.keys()):
            log.debug(u"Running command %s", name)

            attributes = action[name]

            if "defaults" in attributes:
                log.debug(u"Generating defaults for command %s", name)
                defaultsResult = ProcessHelper(attributes['defaults'], stderr=subprocess.PIPE).call()
                log.debug(u"Defaults script for %s output: %s", name, defaultsResult.stdout.decode('utf-8'))
                if defaultsResult.returncode:
                    log.error(u"Defaults script failed for %s: %s", name, defaultsResult.stderr.decode('utf-8'))
                    raise ToolError(u"Defaults script for command %s failed" % name)

                default_attrs = attributes
                default_env = default_attrs.get("env",{})
                attributes = json.loads(defaultsResult.stdout)
                user_env = attributes.get("env",{})
                user_env.update(default_env)
                attributes.update(default_attrs)
                attributes["env"] = user_env

            if not "command" in attributes:
                log.error(u"No command specified for %s", name)
                raise ToolError(u"%s does not specify the 'command' attribute, which is required" % name)

            cwd = os.path.expanduser(attributes["cwd"]) if "cwd" in attributes else None
            env = attributes.get("env", None)

            if "test" in attributes:
                log.debug(u"Running test for command %s", name)
                test = attributes["test"]
                testResult = LoggingProcessHelper(test, name=u'Test for Command %s' % name, env=env, cwd=cwd).call()
                log.debug(u"Test command output: %s", testResult.stdout.decode('utf-8'))
                if testResult.returncode:
                    log.info(u"Test failed with code %s", testResult.returncode)
                    continue
                else:
                    log.debug(u"Test for command %s passed", name)
            else:
                log.debug(u"No test for command %s", name)

            cmd_to_run = attributes["command"]
            if "runas" in attributes:
                if os.name == 'nt':
                    raise ToolError(u'Command %s specified "runas", which is not supported on Windows' % name)

                if isinstance(cmd_to_run, basestring):
                    cmd_to_run = u'su %s -c %s' % (attributes['runas'], cmd_to_run)
                else:
                    cmd_to_run = ['su', attributes['runas'], '-c'] + cmd_to_run

            commandResult = LoggingProcessHelper(cmd_to_run, name=u'Command %s' % name, env=env, cwd=cwd).call()

            if commandResult.returncode:
                log.error(u"Command %s (%s) failed", name, attributes["command"])
                log.debug(u"Command %s output: %s", name, commandResult.stdout.decode('utf-8'))
                if interpret_boolean(attributes.get("ignoreErrors")):
                    log.info("ignoreErrors set to true, continuing build")
                    commands_run.append(name)
                else:
                    raise ToolError(u"Command %s failed" % name)
            else:
                log.info(u"Command %s succeeded", name)
                log.debug(u"Command %s output: %s", name, commandResult.stdout.decode('utf-8'))
                commands_run.append(name)

        return commands_run
コード例 #10
0
    def _run_hook(self, hook, cmd_msg):
        if hook.singleton:
            log.info("Hook %s is configured to run as a singleton", hook.name)
            leader = self.cfn_client.elect_command_leader(
                self.stack_name, cmd_msg['CommandName'],
                cmd_msg['InvocationId'], self.listener_id)
            if leader == self.listener_id:
                log.info(
                    "This listener is the leader.  Continuing with action")
            else:
                log.info("This listener is not the leader; %s is the leader.",
                         leader)
                return True

        action_env = self._get_environment(cmd_msg)
        result_queue = cmd_msg['ResultQueue']

        log.info("Running action for %s", hook.name)
        log.debug("Action environment: %s", action_env)

        action = hook.action
        if hook.runas:
            if os.name == 'posix':
                action = ['su', hook.runas, '-c', action]
            else:
                log.warn('runas is not supported on this operating system')

        result = ProcessHelper(action, stderr=subprocess.PIPE,
                               env=action_env).call()

        log.debug("Action for %s output: %s", hook.name,
                  result.stdout if result.stdout else '<None>')

        if not hook.send_result:
            return True

        result_msg = {
            'DispatcherId': cmd_msg['DispatcherId'],
            'InvocationId': cmd_msg['InvocationId'],
            'CommandName': cmd_msg['CommandName'],
            'Status': "FAILURE" if result.returncode else "SUCCESS",
            'ListenerId': self.listener_id
        }

        if result.returncode:
            result_stderr = result.stderr.rstrip()
            log.warn("Action for %s exited with %s, returning FAILURE",
                     hook.name, result.returncode)
            result_msg['Message'] = result_stderr if len(
                result_stderr
            ) <= 1024 else result_stderr[0:500] + '...' + result_stderr[-500:]
        else:
            result_stdout = result.stdout.rstrip()
            if len(result_stdout) > 1024:
                log.error(
                    "stdout for %s was greater than 1024 in length, which is not allowed",
                    hook.name)
                result_msg['Status'] = 'FAILURE'
                result_msg[
                    'Message'] = 'Result data was longer than 1024 bytes. Started with: ' + result_stdout[
                        0:100]
            else:
                log.info("Action for %s succeeded, returning SUCCESS",
                         hook.name)
                result_msg['Data'] = result_stdout

        try:
            self.sqs_client.send_message(
                result_queue,
                json.dumps(result_msg),
                request_credentials=self._creds_provider.credentials)
        except Exception:
            log.exception('Error sending result; will leave message in queue')
            return False

        return True
コード例 #11
0
    def apply(self, action, auth_config=None):
        """
        Install a set of packages via APT, returning the packages actually installed or updated.

        Arguments:
        action -- a dict of package name to version; version can be empty, a single string or a list of strings

        Exceptions:
        ToolError -- on expected failures (such as a non-zero exit code)
        """

        pkgs_changed = []

        if not action:
            log.debug("No packages specified for APT")
            return pkgs_changed

        cache_result = ProcessHelper(['apt-cache', '-q', 'gencaches']).call()

        if cache_result.returncode:
            log.error("APT gencache failed. Output: %s", cache_result.stdout)
            raise ToolError("Could not create apt cache",
                            cache_result.returncode)

        pkg_specs = []

        for pkg_name in action:
            if action[pkg_name]:
                if isinstance(action[pkg_name], basestring):
                    pkg_keys = ['%s=%s' % (pkg_name, action[pkg_name])]
                else:
                    pkg_keys = [
                        '%s=%s' % (pkg_name, ver) if ver else pkg_name
                        for ver in action[pkg_name]
                    ]
            else:
                pkg_keys = [pkg_name]

            pkgs_filtered = [
                pkg_key for pkg_key in pkg_keys
                if self._pkg_filter(pkg_key, pkg_name)
            ]
            if pkgs_filtered:
                pkg_specs.extend(pkgs_filtered)
                pkgs_changed.append(pkg_name)

        if not pkg_specs:
            log.info("All APT packages were already installed")
            return []

        log.info("Attempting to install %s via APT", pkg_specs)

        env = dict(os.environ)
        env['DEBIAN_FRONTEND'] = 'noninteractive'

        result = ProcessHelper(['apt-get', '-q', '-y', 'install'] + pkg_specs,
                               env=env).call()

        if result.returncode:
            log.error("apt-get failed. Output: %s", result.stdout)
            raise ToolError("Could not successfully install APT packages",
                            result.returncode)

        log.info("APT installed %s", pkgs_changed)
        log.debug("APT output: %s", result.stdout)

        return pkgs_changed
コード例 #12
0
    def apply(self, action, auth_config=None):
        """
        Install a set of packages via yum, returning the packages actually installed or updated.

        Arguments:
        action -- a dict of package name to version; version can be empty, a single string or a list of strings

        Exceptions:
        ToolError -- on expected failures (such as a non-zero exit code)
        """

        pkgs_changed = []

        if not action.keys():
            log.debug("No packages specified for yum")
            return pkgs_changed

        cache_result = ProcessHelper(['yum', '-y', 'makecache']).call()

        if cache_result.returncode:
            log.error("Yum makecache failed. Output: %s", cache_result.stdout)
            raise ToolError("Could not create yum cache",
                            cache_result.returncode)

        pkg_specs_to_upgrade = []
        pkg_specs_to_downgrade = []

        for pkg_name in action:
            if action[pkg_name]:
                if isinstance(action[pkg_name], basestring):
                    pkg_ver = action[pkg_name]
                else:
                    # Yum only cares about one version anyway... so take the max specified version in the list
                    pkg_ver = RpmTool.max_version(action[pkg_name])
            else:
                pkg_ver = None

            pkg_spec = '%s-%s' % (pkg_name, pkg_ver) if pkg_ver else pkg_name

            if self._pkg_installed(pkg_spec):
                # If the EXACT requested spec is installed, don't do anything
                log.debug("%s will not be installed as it is already present",
                          pkg_spec)
            elif not self._pkg_available(pkg_spec):
                # If the requested spec is not available, blow up
                log.error("%s is not available to be installed", pkg_spec)
                raise ToolError(
                    "Yum does not have %s available for installation" %
                    pkg_spec)
            elif not pkg_ver:
                # If they didn't request a specific version, always upgrade
                pkg_specs_to_upgrade.append(pkg_spec)
                pkgs_changed.append(pkg_name)
            else:
                # They've requested a specific version that's available but not installed.
                # Figure out if it's an upgrade or a downgrade
                installed_version = RpmTool.get_package_version(
                    pkg_name, False)[1]
                if self._should_upgrade(pkg_ver, installed_version):
                    pkg_specs_to_upgrade.append(pkg_spec)
                    pkgs_changed.append(pkg_name)
                else:
                    log.debug("Downgrading to %s from installed version %s",
                              pkg_spec, installed_version)
                    pkg_specs_to_downgrade.append(pkg_spec)
                    pkgs_changed.append(pkg_name)

        if not pkgs_changed:
            log.debug("All yum packages were already installed")
            return []

        if pkg_specs_to_upgrade:
            log.debug("Installing/updating %s via yum", pkg_specs_to_upgrade)

            result = ProcessHelper(['yum', '-y', 'install'] +
                                   pkg_specs_to_upgrade).call()

            if result.returncode:
                log.error("Yum failed. Output: %s", result.stdout)
                raise ToolError(
                    "Could not successfully install/update yum packages",
                    result.returncode)

        if pkg_specs_to_downgrade:
            log.debug("Downgrading %s via yum", pkg_specs_to_downgrade)

            result = ProcessHelper(['yum', '-y', 'downgrade'] +
                                   pkg_specs_to_downgrade).call()

            if result.returncode:
                log.error("Yum failed. Output: %s", result.stdout)
                raise ToolError(
                    "Could not successfully downgrade yum packages",
                    result.returncode)

        log.info("Yum installed %s", pkgs_changed)

        return pkgs_changed
コード例 #13
0
    def _pkg_installed(self, pkg):
        result = ProcessHelper(['yum', '-C', '-y', 'list', 'installed',
                                pkg]).call()

        return result.returncode == 0