def run(self, args, login_credentials = None, extra_env = None, no_output = False, raise_error = False, error_message = None): check.check_string_seq(args) check.check_dict(extra_env, allow_none = True) check.check_bool(raise_error) check.check_string(error_message, allow_none = True) self._log.log_method_d() exe = vmware_app.vmrun_exe_path() auth_args = self._make_vmrun_auth_args(login_credentials) vmrun_args = [ exe ] + auth_args + list(args) self._log.log_d('run: vmrun_args={}'.format(vmrun_args)) env = os_env.clone_current_env(d = extra_env) process = subprocess.Popen(vmrun_args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, shell = False, env = env) if no_output: output = None else: output_bytes, _ = process.communicate() output = codecs.decode(output_bytes, 'utf-8') exit_code = process.wait() self._log.log_d('run: exit_code={} output="{}"'.format(exit_code, output)) if exit_code != 0 and raise_error: if not error_message: args_flat = ' '.join(vmrun_args) error_message = 'vmrun command failed: {}\n{}'.format(args_flat, output) raise vmware_error(error_message, status_code = exit_code) result = self._run_result(output, exit_code, vmrun_args) self._log.log_d('run: result: {} - {}'.format(result.exit_code, result.output)) return result
def call_pyinstaller(clazz, args, build_dir = None, replace_env = None): check.check_string_seq(args) check.check_string(build_dir, allow_none = True) check.check_dict(replace_env, check.STRING_TYPES, check.STRING_TYPES) cmd = command_line.parse_args(args) replace_env = replace_env or {} env = os_env.clone_current_env(d = {}) env.update(replace_env) clazz._log.log_d('using env: {}'.format(pprint.pformat(env))) clazz._log.log_d('calling pyinstaller: {}'.format(' '.join(cmd))) if build_dir: file_util.mkdir(build_dir) dist_dir = path.join(build_dir, 'dist') work_dir = path.join(build_dir, 'work') spec_dir = path.join(build_dir, 'spec') args = args[:] args.extend([ '--distpath', dist_dir ]) args.extend([ '--workpath', work_dir ]) args.extend([ '--specpath', spec_dir ]) try: with env_override(env = env) as _: PyInstaller_run(pyi_args = args, pyi_config = None) except Exception as ex: raise pyinstaller_error(str(ex))
def _call_softwareupdate(clazz, args, verbose): check.check_string_seq(args) check.check_bool(verbose) command_line.check_args_type(args) args = object_util.listify(args) exe = which.which('softwareupdate') if not exe: raise softwareupdater_error('softwareupdate not found') clazz._log.log_d('_call_softwareupdate: exe={} args={}'.format( exe, args)) cmd = [exe] + args env = os_env.clone_current_env() rv = execute.execute(cmd, env=env, stderr_to_stdout=True, raise_error=False, non_blocking=verbose) if rv.exit_code != 0: cmd_flat = ' '.join(cmd) msg = 'softwareupdate command failed: {} - {}\n{}'.format( cmd, rv.exit_code, rv.stdout) raise softwareupdater_error(msg, status_code=rv.exit_code) return rv
def call_pkgutil(clazz, args, msg=None, use_sudo=False): check.check_string_seq(args) check.check_string(msg, allow_none=True) check.check_bool(use_sudo) env = os_env.clone_current_env(d={}) rv = pkgutil_command.call_command(args, raise_error=False, env=env, use_sudo=use_sudo) if rv.exit_code != 0: if not msg: cmd_flat = ' '.join(args) msg = 'pkgutil command failed: {}\n{}'.format( cmd_flat, rv.stdout) raise pkgutil_error(msg) return rv
def call_docker(clazz, args, cwd=None, non_blocking=True, shell=False): exe = which.which('docker') if not exe: raise docker_error('docker not found') cmd = [exe] + command_line.parse_args(args) env = os_env.clone_current_env(d={}) rv = execute.execute(cmd, env=env, shell=shell, cwd=cwd, stderr_to_stdout=True, non_blocking=non_blocking, raise_error=False) if rv.exit_code != 0: cmd_flag = ' '.join(cmd) msg = 'docker command failed: {}\n{}'.format(cmd_flag, rv.stdout) raise docker_error(msg) return rv
def call_sudo(clazz, args, options=None): check.check_sudo_cli_options(options, allow_none=True) command_line.check_args_type(args) args = object_util.listify(args) options = options or sudo_cli_options() exe = which.which('sudo') if not exe: raise sudo_error('sudo not found') clazz._log.log_d('sudo: exe={} args={} options={}'.format( exe, args, options)) cmd = [exe] tmp_askpass = None askpass_env = {} if options.password: tmp_askpass = clazz._make_temp_askpass(options.password) askpass_env = {'SUDO_ASKPASS': tmp_askpass} cmd.append('--askpass') if options.prompt: cmd.extend(['--prompt', '"{}"'.format(options.prompt)]) cmd.extend(args) env = os_env.clone_current_env(d=askpass_env) try: rv = execute.execute(cmd, env=env, cwd=options.working_dir, stderr_to_stdout=True, raise_error=False, non_blocking=options.verbose) if rv.exit_code != 0: if options.error_message: msg = options.error_message else: cmd_flat = ' '.join(cmd) msg = 'sudo command failed: {}\n{}'.format( cmd_flat, rv.stdout) raise sudo_error(msg) return rv finally: if tmp_askpass: file_util.remove(tmp_askpass)
def call_program(self, args, **kargs): 'Call a program with the right environment' command_line.check_args_type(args) kargs = copy.deepcopy(kargs) self._log.log_method_d() self._log.log_d('call_program: args={}'.format(args)) parsed_args = command_line.parse_args(args) self._log.log_d('call_program: parsed_args={}'.format(parsed_args)) env = os_env.clone_current_env() env.update(self.env) PATH = env_var(env, 'PATH') PYTHONPATH = env_var(env, 'PYTHONPATH') if 'env' in kargs: kargs_env = kargs['env'] del kargs['env'] if 'PATH' in kargs_env: PATH.append(kargs_env['PATH']) del kargs_env['PATH'] if 'PYTHONPATH' in kargs_env: PYTHONPATH.append(kargs_env['PYTHONPATH']) del kargs_env['PYTHONPATH'] env.update(kargs_env) PATH.prepend(self.PATH) PYTHONPATH.prepend(self.PYTHONPATH) kargs['env'] = env self._log.log_d('call_program: env={}'.format(env)) kargs['shell'] = True kargs['check_python_script'] = False for key, value in sorted(env.items()): self._log.log_d('call_program({}): ENV: {}={}'.format(args[0], key, value)) return execute.execute(parsed_args, **kargs)
def test_env_override_push_pop(self): original_env = os_env.clone_current_env() with env_override() as env: env.push() env.set('FOO', '666') self.assertEqual(self._dict_combine(original_env, {'FOO': '666'}), os_env.clone_current_env()) env.push() env.set('BAR', '667') self.assertEqual( self._dict_combine(original_env, { 'FOO': '666', 'BAR': '667' }), os_env.clone_current_env()) env.pop() self.assertEqual(self._dict_combine(original_env, {'FOO': '666'}), os_env.clone_current_env()) env.pop() self.assertEqual(original_env, os_env.clone_current_env()) self.assertEqual(original_env, os_env.clone_current_env())
def call_git(clazz, root, args, raise_error=True, extra_env=None, num_tries=None, retry_wait_seconds=None): check.check_string(root) command_line.check_args_type(args) check.check_bool(raise_error) check.check_dict(extra_env, check.STRING_TYPES, check.STRING_TYPES, allow_none=True) check.check_int(num_tries, allow_none=True) check.check_float(retry_wait_seconds, allow_none=True) #print('args={}'.format(args)) if isinstance(args, (list, tuple)): parsed_args = list(args) else: parsed_args = command_line.parse_args(args) num_tries = num_tries if num_tries != None else clazz._DEFAULT_NUM_TRIES retry_wait_seconds = retry_wait_seconds if retry_wait_seconds != None else clazz._DEFAULT_RETRY_WAIT_SECONDS if num_tries < 1 or num_tries >= clazz._MAX_NUM_TRIES: raise git_error( 'num_tries should be between 1 and {} instead of "{}"'.format( clazz._DEFAULT_NUM_TRIES, num_tries)) if retry_wait_seconds < clazz._MIN_RETRY_WAIT_SECONDS or retry_wait_seconds >= clazz._MAX_RETRY_WAIT_SECONDS: raise git_error( 'retry_wait_seconds should be between {} and {} instead of "{}"' .format(clazz._MIN_RETRY_WAIT_SECONDS, clazz._MAX_RETRY_WAIT_SECONDS, retry_wait_seconds)) if not hasattr(clazz, '_git_exe'): git_exe = clazz.find_git_exe() if not git_exe: raise git_error('git exe not found in: {}'.format(' '.join( os.environ['PATH'].split(os.pathsep)))) setattr(clazz, '_git_exe', git_exe) git_exe = getattr(clazz, '_git_exe') cmd = [git_exe] + parsed_args clazz.log.log_d('root=%s; cmd=%s' % (root, ' '.join(cmd))) extra_env = extra_env or {} env = os_env.clone_current_env(d=extra_env, prepend=True) last_try_exception = None num_failed_attempts = 0 rv = None for i in range(0, num_tries): try: clazz.log.log_d('call_git: attempt {} of {}: {}'.format( i + 1, num_tries, ' '.join(cmd))) rv = execute.execute(cmd, cwd=root, raise_error=False, env=env) if rv.exit_code == 0: clazz.log.log_i('call_git: success {} of {}: {}'.format( i + 1, num_tries, ' '.join(cmd))) break else: clazz.log.log_i('call_git: failed {} of {}: {}'.format( i + 1, num_tries, ' '.join(cmd))) except Exception as ex: num_failed_attempts += 1 clazz.log.log_w('call_git: failed {} of {}: {}'.format( i + 1, num_tries, ' '.join(cmd))) clazz.log.log_d('call_git: exception: {}'.format(str(ex))) clazz.log.log_d( 'call_git: sleeping {} seconds'.format(retry_wait_seconds)) time.sleep(retry_wait_seconds) last_try_exception = ex if not rv: message = 'git command attempt failed {} times: {} in {}'.format( num_tries, ' '.join(cmd), root) clazz.log.log_w('call_git: {}'.format(message)) raise git_error(message, execute_result=None) # first handle the retry failure if num_tries > 1 and num_failed_attempts == num_tries and last_try_exception: message = 'git command attempt failed {} times: {} in {}\n{}\n{}\n{}'.format( num_tries, ' '.join(cmd), root, str(last_try_exception), rv.stderr, rv.stdout) clazz.log.log_w('call_git: {}'.format(message)) raise git_error(message, execute_result=rv) # handle raise_error if needed if rv.exit_code != 0 and raise_error: message = 'git command failed: {} in {}\n{}\n{}\n{}'.format( ' '.join(cmd), root, str(last_try_exception), rv.stderr, rv.stdout) clazz.log.log_w('call_git: {}'.format(message)) raise git_error(message, execute_result=rv) #print('rv={}'.format(rv)) return rv
def main(self): p = argparse.ArgumentParser() vmware_options_cli_args.add_arguments(p) p.add_argument('--tail-log', action = 'store_true', default = False, help = 'Tail the log [ False ]') p.add_argument('--dir', action = 'store', default = os.getcwd(), dest = 'source_dir', help = 'Directory to use for the package [ False ]') p.add_argument('-o', '--output', action = 'store', default = None, dest = 'output_filename', help = 'Output the log to filename instead of stdout [ False ]') p.add_argument('--clone-vm', action = 'store_true', default = False, help = 'Run programs in a clone of the vm [ False ]') p.add_argument('vm_id', action = 'store', default = None, help = 'The vmware vmx filename for the vm to test [ None ]') p.add_argument('entry_command_args', action = 'store', default = [], nargs = '*', help = 'Optional entry command args [ ]') args = p.parse_args() self._debug = args.debug self._name = path.basename(sys.argv[0]) tmp_dir = tempfile.mkdtemp() tar_util.copy_tree(args.source_dir, tmp_dir, excludes = self._PACKAGE_EXCLUDES) entry_command_path = path.join(tmp_dir, self._ENTRY_COMMAND_FILENAME) file_util.save(entry_command_path, content = self._ENTRY_COMMAND_CONTENT) env = os_env.clone_current_env(d = { 'xBES_LOG': 'vmware=debug', }) extra_args = [] if args.debug: extra_args.append('--debug') if args.tty: extra_args.extend([ '--tty', tty ]) if args.tail_log: extra_args.append('--tail-log') if args.clone_vm: extra_args.append('--clone-vm') if args.output_filename: extra_args.extend([ '--output', args.output_filename ]) if args.config_filename: print(config_filename) extra_args.extend([ '--config', args.config_filename ]) if args.vmrest_username: extra_args.extend([ '--vmrest-username', args.vmrest_username ]) if args.vmrest_password: extra_args.extend([ '--vmrest-password', args.vmrest_password ]) if args.vmrest_port: extra_args.extend([ '--vmrest-port', str(args.vmrest_port) ]) if args.login_username: extra_args.extend([ '--login-username', args.login_username ]) if args.login_password: extra_args.extend([ '--login-password', args.login_password ]) cmd = [ 'bin/best.py', 'vmware', 'vm_run_package', ] + extra_args + [ args.vm_id, tmp_dir, self._ENTRY_COMMAND_FILENAME, ] + args.entry_command_args self._log.log_d('cmd={}'.format(' '.join([ str(x) for x in cmd ]))) rv = execute.execute(cmd, env = env, raise_error = False, shell = False, non_blocking = True, stderr_to_stdout = True) if rv.exit_code != 0: print(rv.stdout) return rv.exit_code
def test_env_override_set(self): original_env = os_env.clone_current_env() with env_override() as env: env.set('FOO', '666') env.set('BAR', 'hi') self.assertEqual(original_env, os_env.clone_current_env())
def test_env_override_init(self): original_env = os_env.clone_current_env() with env_override({'FOO': '666', 'BAR': 'hi'}) as env: pass self.assertEqual(original_env, os_env.clone_current_env())