예제 #1
0
    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(),
        )
예제 #2
0
파일: __init__.py 프로젝트: kcns008/maas
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
예제 #3
0
파일: __init__.py 프로젝트: tai271828/maas
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
예제 #4
0
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