def _on_start(self, persona, component_order, instances): LOG.info("Booting up your components.") LOG.debug("Starting environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64) self._establish_passwords(component_order, instances) self._verify_components(component_order, instances) self._warm_components(component_order, instances)
def _on_start(self, persona, groups): LOG.info("Booting up your components.") LOG.debug("Starting environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64) sh.mkdirslist(self.phase_dir) self._verify_components(groups) self._warm_components(groups)
def _on_finish(self, persona, groups): LOG.info("Tearing down your components.") LOG.debug("Final environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64)
def _on_start(self, persona, component_order, instances): LOG.info("Booting up your components.") LOG.debug("Starting environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64) sh.mkdirslist(self.phase_dir) self._establish_passwords(component_order, instances) self._verify_components(component_order, instances) self._warm_components(component_order, instances)
def _on_finish(self, persona, component_order, instances): LOG.info("Tearing down your components.") LOG.debug("Final environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64) exports_filename = "%s.rc" % (self.name) self._write_exports(component_order, instances, sh.joinpths("/etc/anvil", exports_filename))
def _on_finish(self, persona, component_order, instances): LOG.info("Tearing down your components.") LOG.debug("Final environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64)
def execute(cmd, process_input=None, check_exit_code=True, cwd=None, shell=False, env_overrides=None, stdout_fh=subprocess.PIPE, stderr_fh=subprocess.PIPE): """Helper method to execute a command through subprocess. :param cmd: Command passed to subprocess.Popen. :param process_input: Input send to opened process. :param check_exit_code: Specifies whether to check process return code. If return code is other then `0` - exception will be raised. :param cwd: The child's current directory will be changed to `cwd` before it is executed. :param shell: Specifies whether to use the shell as the program to execute. :param env_overrides: Process environment parameters to override. :param stdout_fh: Stdout file handler. :param stderr_fh: Stderr file handler. :returns: A tuple, (stdout, stderr) from the spawned process. :raises: :class:`exceptions.ProcessExecutionError` when process ends with other then `0` return code. """ # Ensure all string args (i.e. for those that send ints, etc.). cmd = map(str, cmd) # NOTE(skudriashev): If shell is True, it is recommended to pass args as a # string rather than as a sequence. str_cmd = subprocess.list2cmdline(cmd) if shell: cmd = str_cmd LOG.debug('Running shell cmd: %r' % cmd) else: LOG.debug('Running cmd: %r' % cmd) if process_input is not None: process_input = str(process_input) LOG.debug('Process input: %s' % process_input) if cwd: LOG.debug('Process working directory: %r' % cwd) # Override process environment in needed. process_env = None if env_overrides and len(env_overrides): process_env = env.get() for k, v in env_overrides.items(): process_env[k] = str(v) # Run command process. exec_kwargs = { 'stdin': subprocess.PIPE, 'stdout': stdout_fh, 'stderr': stderr_fh, 'close_fds': True, 'shell': shell, 'cwd': cwd, 'env': process_env, } result = ("", "") try: obj = subprocess.Popen(cmd, **exec_kwargs) result = obj.communicate(process_input) except OSError as e: raise excp.ProcessExecutionError(str_cmd, exec_kwargs=exec_kwargs, description="%s: [%s, %s]" % (e, e.errno, e.strerror)) else: rc = obj.returncode # Handle process exit code. stdout = result[0] or "" stderr = result[1] or "" if rc != 0 and check_exit_code: # Raise exception if return code is not `0`. e = excp.ProcessExecutionError(str_cmd, exec_kwargs=exec_kwargs, stdout=stdout, stderr=stderr, exit_code=rc, where_output="debug log") LOG.debug("Stdout: %s", e.stdout) LOG.debug("Stderr: %s", e.stderr) raise e return stdout, stderr
def execute( cmd, process_input=None, check_exit_code=True, cwd=None, shell=False, env_overrides=None, stdout_fh=None, stderr_fh=None, stdout_fn=None, stderr_fn=None, trace_writer=None, ): """Helper method to execute command. :param cmd: Passed to subprocess.Popen :param process_input: Send to opened process :param check_exit_code: Single `bool`, `int`, or `list` of allowed exit codes. By default, only 0 exit code is allowed. Raise :class:`exceptions.ProcessExecutionError` unless program exits with one of these code :returns: a tuple, (stdout, stderr) from the spawned process, or None if the command fails """ if isinstance(check_exit_code, (bool)): ignore_exit_code = not check_exit_code check_exit_code = [0] elif isinstance(check_exit_code, (int)): check_exit_code = [check_exit_code] # Ensure all string args (ie for those that send ints and such...) execute_cmd = [str(c) for c in cmd] # From the docs it seems a shell command must be a string?? # TODO(harlowja) this might not really be needed? str_cmd = " ".join(shellquote(word) for word in cmd) if shell: execute_cmd = str_cmd if not shell: LOG.debug("Running cmd: %r" % (execute_cmd)) else: LOG.debug("Running shell cmd: %r" % (execute_cmd)) if process_input is not None: LOG.debug("With stdin: %s" % (process_input)) if cwd: LOG.debug("In working directory: %r" % (cwd)) if stdout_fn is not None and stdout_fh is not None: LOG.warn("Stdout file handles and stdout file names can not be used simultaneously!") if stderr_fn is not None and stderr_fh is not None: LOG.warn("Stderr file handles and stderr file names can not be used simultaneously!") process_env = None if env_overrides and len(env_overrides): process_env = env.get() for (k, v) in env_overrides.items(): process_env[k] = str(v) rc = None result = ("", "") if is_dry_run(): rc = 0 else: stdin_fh = subprocess.PIPE if stdout_fn or (stdout_fh is None): stdout_fh = subprocess.PIPE if stderr_fn or (stderr_fh is None): stderr_fh = subprocess.PIPE try: obj = subprocess.Popen( execute_cmd, stdin=stdin_fh, stdout=stdout_fh, stderr=stderr_fh, close_fds=True, cwd=cwd, shell=shell, env=process_env, ) if process_input is not None: result = obj.communicate(str(process_input)) else: result = obj.communicate() except OSError as e: raise excp.ProcessExecutionError(description="%s: [%s, %s]" % (e, e.errno, e.strerror), cmd=str_cmd) rc = obj.returncode if stdout_fh != subprocess.PIPE: stdout = "<redirected to %s>" % (stdout_fn or stdout_fh) else: stdout = result[0] or "" if stderr_fh != subprocess.PIPE: stderr = "<redirected to %s>" % (stderr_fn or stderr_fh) else: stderr = result[1] or "" if (not ignore_exit_code) and (rc not in check_exit_code): raise excp.ProcessExecutionError(exit_code=rc, stdout=stdout, stderr=stderr, cmd=str_cmd) else: # Log it anyway if rc not in check_exit_code: LOG.debug( "A failure may of just happened when running command %r [%s] (%s, %s)", str_cmd, rc, stdout, stderr ) # See if a requested storage place was given for stderr/stdout for name, handle in ((stdout_fn, stdout), (stderr_fn, stderr)): if name: write_file(name, handle) if trace_writer: trace_writer.file_touched(name) return (stdout, stderr)
def execute(*cmd, **kwargs): process_input = kwargs.pop('process_input', None) check_exit_code = kwargs.pop('check_exit_code', [0]) cwd = kwargs.pop('cwd', None) env_overrides = kwargs.pop('env_overrides', None) close_stdin = kwargs.pop('close_stdin', False) ignore_exit_code = kwargs.pop('ignore_exit_code', False) if isinstance(check_exit_code, bool): ignore_exit_code = not check_exit_code check_exit_code = [0] elif isinstance(check_exit_code, int): check_exit_code = [check_exit_code] run_as_root = kwargs.pop('run_as_root', False) shell = kwargs.pop('shell', False) # Ensure all string args execute_cmd = [] for c in cmd: execute_cmd.append(str(c)) # From the docs it seems a shell command must be a string?? # TODO(harlowja) this might not really be needed? str_cmd = " ".join(execute_cmd) if shell: execute_cmd = str_cmd.strip() stdin_fh = subprocess.PIPE stdout_fh = subprocess.PIPE stderr_fh = subprocess.PIPE close_file_descriptors = True if 'stdout_fh' in kwargs.keys(): stdout_fh = kwargs.get('stdout_fh') if 'stdin_fh' in kwargs.keys(): stdin_fh = kwargs.get('stdin_fh') process_input = None if 'stderr_fh' in kwargs.keys(): stderr_fh = kwargs.get('stderr_fh') if not shell: LOG.debug('Running cmd: %r' % (execute_cmd)) else: LOG.debug('Running shell cmd: %r' % (execute_cmd)) if process_input is not None: LOG.debug('With stdin: %s' % (process_input)) if cwd: LOG.debug("In working directory: %r" % (cwd)) process_env = None if env_overrides and len(env_overrides): process_env = env.get() for (k, v) in env_overrides.items(): process_env[k] = str(v) else: process_env = env.get() # LOG.debug("With environment %s", process_env) demoter = None def demoter_functor(user_uid, user_gid): def doit(): os.setregid(user_gid, user_gid) os.setreuid(user_uid, user_uid) return doit if not run_as_root: (user_uid, user_gid) = get_suids() if user_uid is None or user_gid is None: pass else: demoter = demoter_functor(user_uid=user_uid, user_gid=user_gid) rc = None result = None with Rooted(run_as_root): if is_dry_run(): rc = 0 result = ('', '') else: try: obj = subprocess.Popen(execute_cmd, stdin=stdin_fh, stdout=stdout_fh, stderr=stderr_fh, close_fds=close_file_descriptors, cwd=cwd, shell=shell, preexec_fn=demoter, env=process_env) if process_input is not None: result = obj.communicate(str(process_input)) else: result = obj.communicate() except OSError as e: raise excp.ProcessExecutionError(description="%s: [%s, %s]" % (e, e.errno, e.strerror), cmd=str_cmd) if (stdin_fh != subprocess.PIPE and obj.stdin and close_stdin): obj.stdin.close() rc = obj.returncode if not result: result = ("", "") (stdout, stderr) = result if stdout is None: stdout = '' if stderr is None: stderr = '' if (not ignore_exit_code) and (rc not in check_exit_code): raise excp.ProcessExecutionError(exit_code=rc, stdout=stdout, stderr=stderr, cmd=str_cmd) else: # Log it anyway if rc not in check_exit_code: LOG.debug("A failure may of just happened when running command %r [%s] (%s, %s)", str_cmd, rc, stdout, stderr) # See if a requested storage place was given for stderr/stdout trace_writer = kwargs.get('trace_writer') stdout_fn = kwargs.get('stdout_fn') if stdout_fn: write_file(stdout_fn, stdout) if trace_writer: trace_writer.file_touched(stdout_fn) stderr_fn = kwargs.get('stderr_fn') if stderr_fn: write_file(stderr_fn, stderr) if trace_writer: trace_writer.file_touched(stderr_fn) return (stdout, stderr)
def execute(cmd, process_input=None, check_exit_code=True, cwd=None, shell=False, env_overrides=None, stdout_fh=subprocess.PIPE, stderr_fh=subprocess.PIPE): """Helper method to execute a command through subprocess. :param cmd: Command passed to subprocess.Popen. :param process_input: Input send to opened process. :param check_exit_code: Specifies whether to check process return code. If return code is other then `0` - exception will be raised. :param cwd: The child's current directory will be changed to `cwd` before it is executed. :param shell: Specifies whether to use the shell as the program to execute. :param env_overrides: Process environment parameters to override. :param stdout_fh: Stdout file handler. :param stderr_fh: Stderr file handler. :returns: A tuple, (stdout, stderr) from the spawned process. :raises: :class:`exceptions.ProcessExecutionError` when process ends with other then `0` return code. """ # Ensure all string args (i.e. for those that send ints, etc.). cmd = map(str, cmd) # NOTE(skudriashev): If shell is True, it is recommended to pass args as a # string rather than as a sequence. str_cmd = subprocess.list2cmdline(cmd) if shell: cmd = str_cmd LOG.debug('Running shell cmd: %r' % cmd) else: LOG.debug('Running cmd: %r' % cmd) if process_input is not None: process_input = str(process_input) LOG.debug('Process input: %s' % process_input) if cwd: LOG.debug('Process working directory: %r' % cwd) # Override process environment in needed. process_env = None if env_overrides and len(env_overrides): process_env = env.get() for k, v in env_overrides.items(): LOG.debug("Using environment override '%s' => '%s'", k, v) process_env[k] = str(v) # Run command process. exec_kwargs = { 'stdin': subprocess.PIPE, 'stdout': stdout_fh, 'stderr': stderr_fh, 'close_fds': True, 'shell': shell, 'cwd': cwd, 'env': process_env, } result = ("", "") try: obj = subprocess.Popen(cmd, **exec_kwargs) result = obj.communicate(process_input) except OSError as e: raise excp.ProcessExecutionError( str_cmd, exec_kwargs=exec_kwargs, description="%s: [%s, %s]" % (e, e.errno, e.strerror) ) else: rc = obj.returncode # Handle process exit code. stdout = result[0] or "" stderr = result[1] or "" if rc != 0 and check_exit_code: # Raise exception if return code is not `0`. e = excp.ProcessExecutionError(str_cmd, exec_kwargs=exec_kwargs, stdout=stdout, stderr=stderr, exit_code=rc, where_output="debug log") LOG.debug("Stdout: %s", e.stdout) LOG.debug("Stderr: %s", e.stderr) raise e return stdout, stderr
def execute(cmd, process_input=None, check_exit_code=True, cwd=None, shell=False, env_overrides=None, stdout_fh=None, stderr_fh=None, stdout_fn=None, stderr_fn=None, trace_writer=None): """Helper method to execute command. :param cmd: Passed to subprocess.Popen :param process_input: Send to opened process :param check_exit_code: Single `bool`, `int`, or `list` of allowed exit codes. By default, only 0 exit code is allowed. Raise :class:`exceptions.ProcessExecutionError` unless program exits with one of these code :returns: a tuple, (stdout, stderr) from the spawned process, or None if the command fails """ if isinstance(check_exit_code, (bool)): ignore_exit_code = not check_exit_code check_exit_code = [0] elif isinstance(check_exit_code, (int)): check_exit_code = [check_exit_code] # Ensure all string args (ie for those that send ints and such...) execute_cmd = [str(c) for c in cmd] # From the docs it seems a shell command must be a string?? # TODO(harlowja) this might not really be needed? str_cmd = " ".join(shellquote(word) for word in cmd) if shell: execute_cmd = str_cmd if not shell: LOG.debug('Running cmd: %r' % (execute_cmd)) else: LOG.debug('Running shell cmd: %r' % (execute_cmd)) if process_input is not None: LOG.debug('With stdin: %s' % (process_input)) if cwd: LOG.debug("In working directory: %r" % (cwd)) if stdout_fn is not None and stdout_fh is not None: LOG.warn("Stdout file handles and stdout file names can not be used simultaneously!") if stderr_fn is not None and stderr_fh is not None: LOG.warn("Stderr file handles and stderr file names can not be used simultaneously!") process_env = None if env_overrides and len(env_overrides): process_env = env.get() for (k, v) in env_overrides.items(): process_env[k] = str(v) rc = None result = ("", "") if is_dry_run(): rc = 0 else: stdin_fh = subprocess.PIPE if stdout_fn or (stdout_fh is None): stdout_fh = subprocess.PIPE if stderr_fn or (stderr_fh is None): stderr_fh = subprocess.PIPE try: obj = subprocess.Popen(execute_cmd, stdin=stdin_fh, stdout=stdout_fh, stderr=stderr_fh, close_fds=True, cwd=cwd, shell=shell, env=process_env) if process_input is not None: result = obj.communicate(str(process_input)) else: result = obj.communicate() except OSError as e: raise excp.ProcessExecutionError(description="%s: [%s, %s]" % (e, e.errno, e.strerror), cmd=str_cmd) rc = obj.returncode if stdout_fh != subprocess.PIPE: stdout = "<redirected to %s>" % (stdout_fn or stdout_fh) else: stdout = result[0] or "" if stderr_fh != subprocess.PIPE: stderr = "<redirected to %s>" % (stderr_fn or stderr_fh) else: stderr = result[1] or "" if (not ignore_exit_code) and (rc not in check_exit_code): raise excp.ProcessExecutionError(exit_code=rc, stdout=stdout, stderr=stderr, cmd=str_cmd) else: # Log it anyway if rc not in check_exit_code: LOG.debug("A failure may of just happened when running command %r [%s] (%s, %s)", str_cmd, rc, stdout, stderr) # See if a requested storage place was given for stderr/stdout for name, handle in ((stdout_fn, stdout), (stderr_fn, stderr)): if name: write_file(name, handle) if trace_writer: trace_writer.file_touched(name) return (stdout, stderr)
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sys import termcolor from anvil import env from anvil import type_utils as tu COLORS = termcolor.COLORS.keys() LOG_COLOR = True if 'LOG_COLOR' in env.get(): LOG_COLOR = tu.make_bool(env.get_key('LOG_COLOR')) if not sys.stdout.isatty(): LOG_COLOR = False def color_enabled(): return LOG_COLOR def quote(data, quote_color='green', **kargs): if not color_enabled(): return "'%s'" % (data) else: text = str(data) if len(text) == 0:
def execute(*cmd, **kwargs): process_input = kwargs.pop('process_input', None) check_exit_code = kwargs.pop('check_exit_code', [0]) cwd = kwargs.pop('cwd', None) env_overrides = kwargs.pop('env_overrides', None) close_stdin = kwargs.pop('close_stdin', False) ignore_exit_code = kwargs.pop('ignore_exit_code', False) if isinstance(check_exit_code, bool): ignore_exit_code = not check_exit_code check_exit_code = [0] elif isinstance(check_exit_code, int): check_exit_code = [check_exit_code] run_as_root = kwargs.pop('run_as_root', False) shell = kwargs.pop('shell', False) # Ensure all string args execute_cmd = [] for c in cmd: execute_cmd.append(str(c)) # From the docs it seems a shell command must be a string?? # TODO(harlowja) this might not really be needed? str_cmd = " ".join(execute_cmd) if shell: execute_cmd = str_cmd.strip() stdin_fh = subprocess.PIPE stdout_fh = subprocess.PIPE stderr_fh = subprocess.PIPE close_file_descriptors = True if 'stdout_fh' in kwargs.keys(): stdout_fh = kwargs.get('stdout_fh') if 'stdin_fh' in kwargs.keys(): stdin_fh = kwargs.get('stdin_fh') process_input = None if 'stderr_fh' in kwargs.keys(): stderr_fh = kwargs.get('stderr_fh') if not shell: LOG.debug('Running cmd: %r' % (execute_cmd)) else: LOG.debug('Running shell cmd: %r' % (execute_cmd)) if process_input is not None: LOG.debug('With stdin: %s' % (process_input)) if cwd: LOG.debug("In working directory: %r" % (cwd)) process_env = None if env_overrides and len(env_overrides): process_env = env.get() for (k, v) in env_overrides.items(): process_env[k] = str(v) else: process_env = env.get() # LOG.debug("With environment %s", process_env) demoter = None def demoter_functor(user_uid, user_gid): def doit(): os.setregid(user_gid, user_gid) os.setreuid(user_uid, user_uid) return doit if not run_as_root: (user_uid, user_gid) = get_suids() if user_uid is None or user_gid is None: pass else: demoter = demoter_functor(user_uid=user_uid, user_gid=user_gid) rc = None result = None with Rooted(run_as_root): if is_dry_run(): rc = 0 result = ('', '') else: try: obj = subprocess.Popen(execute_cmd, stdin=stdin_fh, stdout=stdout_fh, stderr=stderr_fh, close_fds=close_file_descriptors, cwd=cwd, shell=shell, preexec_fn=demoter, env=process_env) if process_input is not None: result = obj.communicate(str(process_input)) else: result = obj.communicate() except OSError as e: raise excp.ProcessExecutionError(description="%s: [%s, %s]" % (e, e.errno, e.strerror), cmd=str_cmd) if (stdin_fh != subprocess.PIPE and obj.stdin and close_stdin): obj.stdin.close() rc = obj.returncode if not result: result = ("", "") (stdout, stderr) = result if stdout is None: stdout = '' if stderr is None: stderr = '' if (not ignore_exit_code) and (rc not in check_exit_code): raise excp.ProcessExecutionError(exit_code=rc, stdout=stdout, stderr=stderr, cmd=str_cmd) else: # Log it anyway if rc not in check_exit_code: LOG.debug( "A failure may of just happened when running command %r [%s] (%s, %s)", str_cmd, rc, stdout, stderr) # See if a requested storage place was given for stderr/stdout trace_writer = kwargs.get('trace_writer') stdout_fn = kwargs.get('stdout_fn') if stdout_fn: write_file(stdout_fn, stdout) if trace_writer: trace_writer.file_touched(stdout_fn) stderr_fn = kwargs.get('stderr_fn') if stderr_fn: write_file(stderr_fn, stderr) if trace_writer: trace_writer.file_touched(stderr_fn) return (stdout, stderr)
def color_enabled(): if 'LOG_COLOR' in env.get() and not tu.make_bool(env.get_key('LOG_COLOR')): return False if not sys.stdout.isatty(): return False return True