def capture(self, proc, timeout=None): scripts_dir = Path(self.useFixture(TempDirectory()).path) combined_path = scripts_dir.joinpath("combined") stdout_path = scripts_dir.joinpath("stdout") stderr_path = scripts_dir.joinpath("stderr") returncode = maas_api_helper.capture_script_output( proc, str(combined_path), str(stdout_path), str(stderr_path), timeout) return ( returncode, stdout_path.read_text(), stderr_path.read_text(), combined_path.read_text(), )
def runscripts(scripts, url, creds, tmpdir): total_scripts = len(scripts) current_script = 1 failed_scripts = [] out_dir = os.path.join(tmpdir, 'out') os.makedirs(out_dir) for script_name in sorted(scripts.keys()): builtin_script = scripts[script_name] signal_wrapper( url, creds, 'WORKING', 'Starting %s [%d/%d]' % (script_name, current_script, total_scripts)) # Write script to /tmp and set it executable script_path = os.path.join(tmpdir, script_name) with open(script_path, 'wb') as f: f.write(builtin_script['content']) st = os.stat(script_path) os.chmod(script_path, st.st_mode | stat.S_IEXEC) combined_path = os.path.join(out_dir, script_name) stdout_name = '%s.out' % script_name stdout_path = os.path.join(out_dir, stdout_name) stderr_name = '%s.err' % script_name stderr_path = os.path.join(out_dir, stderr_name) timeout = builtin_script.get('timeout') if timeout is None: timeout_seconds = None else: timeout_seconds = timeout.seconds try: proc = Popen(script_path, stdout=PIPE, stderr=PIPE) capture_script_output(proc, combined_path, stdout_path, stderr_path, timeout_seconds) except OSError as e: if isinstance(e.errno, int) and e.errno != 0: exit_status = e.errno else: # 2 is the return code bash gives when it can't execute. exit_status = 2 result = str(e).encode() if result == b'': result = b'Unable to execute script' files = { script_name: result, stderr_name: result, } signal_wrapper( url, creds, 'WORKING', files=files, exit_status=exit_status, error='Failed to execute %s [%d/%d]: %d' % (script_name, current_script, total_scripts, exit_status)) failed_scripts.append(script_name) except TimeoutExpired: files = { script_name: open(combined_path, 'rb').read(), stdout_name: open(stdout_path, 'rb').read(), stderr_name: open(stderr_path, 'rb').read(), } signal_wrapper( url, creds, 'TIMEDOUT', files=files, error='Timeout(%s) expired on %s [%d/%d]' % (str(timeout), script_name, current_script, total_scripts)) failed_scripts.append(script_name) else: files = { script_name: open(combined_path, 'rb').read(), stdout_name: open(stdout_path, 'rb').read(), stderr_name: open(stderr_path, 'rb').read(), } signal_wrapper( url, creds, 'WORKING', files=files, exit_status=proc.returncode, error='Finished %s [%d/%d]: %d' % (script_name, current_script, total_scripts, proc.returncode)) if proc.returncode != 0: failed_scripts.append(script_name) current_script += 1 return failed_scripts
def runscripts(scripts, url, creds, tmpdir): total_scripts = len(scripts) current_script = 1 failed_scripts = [] out_dir = os.path.join(tmpdir, "out") os.makedirs(out_dir) for script_name in sorted(scripts.keys()): builtin_script = scripts[script_name] signal_wrapper( url, creds, "WORKING", "Starting %s [%d/%d]" % (script_name, current_script, total_scripts), ) if script_name == LXD_OUTPUT_NAME: # Execute the LXD binary directly as we are already on the # rack controller and don't need to download it. if running_in_snap(): script_path = os.path.join( get_snap_path(), "usr/share/maas/machine-resources", get_architecture().split("/")[0], ) else: script_path = os.path.join( "/usr/share/maas/machine-resources", get_architecture().split("/")[0], ) else: # Write script to /tmp and set it executable script_path = os.path.join(tmpdir, script_name) with open(script_path, "wb") as f: f.write(builtin_script["content"]) st = os.stat(script_path) os.chmod(script_path, st.st_mode | stat.S_IEXEC) combined_path = os.path.join(out_dir, script_name) stdout_name = "%s.out" % script_name stdout_path = os.path.join(out_dir, stdout_name) stderr_name = "%s.err" % script_name stderr_path = os.path.join(out_dir, stderr_name) result_name = "%s.yaml" % script_name result_path = os.path.join(out_dir, result_name) env = copy.deepcopy(os.environ) env["OUTPUT_COMBINED_PATH"] = combined_path env["OUTPUT_STDOUT_PATH"] = stdout_path env["OUTPUT_STDERR_PATH"] = stderr_path env["RESULT_PATH"] = result_path timeout = builtin_script.get("timeout") if timeout is None: timeout_seconds = None else: timeout_seconds = timeout.seconds try: proc = Popen(script_path, stdin=DEVNULL, stdout=PIPE, stderr=PIPE, env=env) capture_script_output(proc, combined_path, stdout_path, stderr_path, timeout_seconds) except OSError as e: if isinstance(e.errno, int) and e.errno != 0: exit_status = e.errno else: # 2 is the return code bash gives when it can't execute. exit_status = 2 result = str(e).encode() if result == b"": result = b"Unable to execute script" files = {script_name: result, stderr_name: result} signal_wrapper( url, creds, "WORKING", files=files, exit_status=exit_status, error="Failed to execute %s [%d/%d]: %d" % (script_name, current_script, total_scripts, exit_status), ) failed_scripts.append(script_name) except TimeoutExpired: files = { script_name: open(combined_path, "rb").read(), stdout_name: open(stdout_path, "rb").read(), stderr_name: open(stderr_path, "rb").read(), } signal_wrapper( url, creds, "TIMEDOUT", files=files, error="Timeout(%s) expired on %s [%d/%d]" % (str(timeout), script_name, current_script, total_scripts), ) failed_scripts.append(script_name) else: files = { script_name: open(combined_path, "rb").read(), stdout_name: open(stdout_path, "rb").read(), stderr_name: open(stderr_path, "rb").read(), } if os.path.exists(result_path): files[result_name] = open(result_path, "rb").read() signal_wrapper( url, creds, "WORKING", files=files, exit_status=proc.returncode, error="Finished %s [%d/%d]: %d" % ( script_name, current_script, total_scripts, proc.returncode, ), ) if proc.returncode != 0: failed_scripts.append(script_name) current_script += 1 return failed_scripts
def runscripts(scripts, url, creds, tmpdir): total_scripts = len(scripts) current_script = 1 failed_scripts = [] out_dir = os.path.join(tmpdir, "out") os.makedirs(out_dir) for script_name in sorted(scripts.keys()): signal_wrapper( url, creds, "WORKING", "Starting %s [%d/%d]" % (script_name, current_script, total_scripts), ) if script_name == LXD_OUTPUT_NAME: # Execute the LXD binary directly as we are already on the # rack controller and don't need to download it. script_path = get_resources_bin_path() else: script_path = os.path.join(os.path.dirname(__file__), script_name) combined_path = os.path.join(out_dir, script_name) stdout_name = "%s.out" % script_name stdout_path = os.path.join(out_dir, stdout_name) stderr_name = "%s.err" % script_name stderr_path = os.path.join(out_dir, stderr_name) result_name = "%s.yaml" % script_name result_path = os.path.join(out_dir, result_name) env = copy.deepcopy(os.environ) env["OUTPUT_COMBINED_PATH"] = combined_path env["OUTPUT_STDOUT_PATH"] = stdout_path env["OUTPUT_STDERR_PATH"] = stderr_path env["RESULT_PATH"] = result_path timeout = 60 try: proc = Popen(script_path, stdin=DEVNULL, stdout=PIPE, stderr=PIPE, env=env) capture_script_output(proc, combined_path, stdout_path, stderr_path, timeout) except OSError as e: if isinstance(e.errno, int) and e.errno != 0: exit_status = e.errno else: # 2 is the return code bash gives when it can't execute. exit_status = 2 result = str(e).encode() if result == b"": result = b"Unable to execute script" files = {script_name: result, stderr_name: result} signal_wrapper( url, creds, "WORKING", files=files, exit_status=exit_status, error="Failed to execute %s [%d/%d]: %d" % (script_name, current_script, total_scripts, exit_status), ) failed_scripts.append(script_name) except TimeoutExpired: files = { script_name: open(combined_path, "rb").read(), stdout_name: open(stdout_path, "rb").read(), stderr_name: open(stderr_path, "rb").read(), } signal_wrapper( url, creds, "TIMEDOUT", files=files, error="Timeout(%s) expired on %s [%d/%d]" % (str(timeout), script_name, current_script, total_scripts), ) failed_scripts.append(script_name) else: files = { script_name: open(combined_path, "rb").read(), stdout_name: open(stdout_path, "rb").read(), stderr_name: open(stderr_path, "rb").read(), } if os.path.exists(result_path): files[result_name] = open(result_path, "rb").read() signal_wrapper( url, creds, "WORKING", files=files, exit_status=proc.returncode, error="Finished %s [%d/%d]: %d" % ( script_name, current_script, total_scripts, proc.returncode, ), ) if proc.returncode != 0: failed_scripts.append(script_name) current_script += 1 return failed_scripts