Exemplo n.º 1
0
 def _get_wsman_command(self, *args):
     base_path = snappy.get_snap_path() or "/"
     return (
         "wsman",
         "-C",
         join(base_path, "etc/openwsman/openwsman_client.conf"),
     ) + args
Exemplo n.º 2
0
def get_resources_bin_path():
    """Return the path of the resources binary."""
    if is_dev_environment():
        path = "src/machine-resources/bin"
    else:
        prefix = get_snap_path() or ""
        path = f"{prefix}/usr/share/maas/machine-resources"
    return os.path.join(path, get_architecture())
Exemplo n.º 3
0
    def _execSupervisorServiceAction(self, service_name, action):
        """Perform the action with the run-supervisorctl command.

        :return: tuple (exit code, std-output, std-error)
        """
        env = get_env_with_bytes_locale()
        cmd = os.path.join(snappy.get_snap_path(), "bin", "run-supervisorctl")
        cmd = (cmd, action, service_name)
        return self._execCmd(cmd, env)
Exemplo n.º 4
0
    def _execSupervisorServiceAction(self, service_name, action):
        """Perform the action with the run-supervisorctl command.

        :return: tuple (exit code, std-output, std-error)
        """
        env = select_c_utf8_bytes_locale()
        cmd = os.path.join(snappy.get_snap_path(), "bin", "run-supervisorctl")
        cmd = (cmd, action, service_name)

        def decode(result):
            out, err, code = result
            return code, out.decode("utf-8"), err.decode("utf-8")

        d = getProcessOutputAndValue(cmd[0], cmd[1:], env=env)
        return d.addCallback(decode)
Exemplo n.º 5
0
def get_maas_common_command():
    """Return path to the maas-rack command.

    In production mode this will just return 'maas-rack', but in
    development mode it will return the path for the current development
    environment.
    """
    # Avoid circular imports.
    from provisioningserver.config import is_dev_environment
    if is_dev_environment():
        from maastesting import root
        return os.path.join(root, 'bin/maas-common')
    elif snappy.running_in_snap():
        # there's no maas-common in the snap as maas-rack is always present
        return os.path.join(snappy.get_snap_path(), 'bin/maas-rack')
    else:
        return get_path('usr/lib/maas/maas-common')
Exemplo n.º 6
0
    def write_config():
        allowed_subnets = Subnet.objects.filter(allow_proxy=True)
        cidrs = [subnet.cidr for subnet in allowed_subnets]
        config = Config.objects.get_configs([
            'http_proxy', 'maas_proxy_port', 'use_peer_proxy',
            'prefer_v4_proxy', 'enable_http_proxy'
        ])

        http_proxy = config["http_proxy"]
        upstream_proxy_enabled = (config["use_peer_proxy"] and http_proxy)
        context = {
            'allowed': allowed_subnets,
            'modified': str(datetime.date.today()),
            'fqdn': socket.getfqdn(),
            'cidrs': cidrs,
            'running_in_snap': snappy.running_in_snap(),
            'snap_path': snappy.get_snap_path(),
            'snap_data_path': snappy.get_snap_data_path(),
            'snap_common_path': snappy.get_snap_common_path(),
            'upstream_peer_proxy': upstream_proxy_enabled,
            'dns_v4_first': config['prefer_v4_proxy'],
            'maas_proxy_port': config['maas_proxy_port'],
        }

        proxy_enabled = config["enable_http_proxy"]
        if proxy_enabled and upstream_proxy_enabled:
            http_proxy_hostname = urlparse(http_proxy).hostname
            http_proxy_port = urlparse(http_proxy).port
            context.update({
                'upstream_proxy_address': http_proxy_hostname,
                'upstream_proxy_port': http_proxy_port,
            })

        template_path = locate_template('proxy', MAAS_PROXY_CONF_TEMPLATE)
        template = tempita.Template.from_filename(template_path,
                                                  encoding="UTF-8")
        try:
            content = template.substitute(context)
        except NameError as error:
            raise ProxyConfigFail(*error.args)
        # Squid prefers ascii.
        content = content.encode("ascii")
        target_path = get_proxy_config_path()
        atomic_write(content, target_path, overwrite=True, mode=0o644)
Exemplo n.º 7
0
    def _execSupervisorServiceAction(self,
                                     service_name,
                                     action,
                                     extra_opts=None):
        """Perform the action with the run-supervisorctl command.

        :return: tuple (exit code, std-output, std-error)
        """
        env = get_env_with_bytes_locale()
        cmd = os.path.join(snappy.get_snap_path(), "bin", "run-supervisorctl")

        # supervisord doesn't support native kill like systemd. Emulate this
        # behaviour by getting the PID of the process and then killing the PID.
        if action == "kill":

            def _kill_pid(result):
                exit_code, stdout, _ = result
                if exit_code != 0:
                    return result
                try:
                    pid = int(stdout.strip())
                except ValueError:
                    pid = 0
                if pid == 0:
                    # supervisorctl returns 0 when the process is already dead
                    # or we where not able to get the actual pid. Nothing to
                    # do, as its already dead.
                    return 0, "", ""
                cmd = ("kill", )
                if extra_opts:
                    cmd += extra_opts
                cmd += ("%s" % pid, )
                return self._execCmd(cmd, env)

            d = self._execCmd((cmd, "pid", service_name), env)
            d.addCallback(_kill_pid)
            return d

        cmd = (cmd, action)
        if extra_opts is not None:
            cmd += extra_opts
        cmd += (service_name, )
        return self._execCmd(cmd, env)
Exemplo n.º 8
0
def write_config(
    allowed_cidrs,
    peer_proxies=None,
    prefer_v4_proxy=False,
    maas_proxy_port=8000,
):
    """Write the proxy configuration."""
    if peer_proxies is None:
        peer_proxies = []

    context = {
        "modified": str(datetime.date.today()),
        "fqdn": socket.getfqdn(),
        "cidrs": allowed_cidrs,
        "running_in_snap": snappy.running_in_snap(),
        "snap_path": snappy.get_snap_path(),
        "snap_data_path": snappy.get_snap_data_path(),
        "snap_common_path": snappy.get_snap_common_path(),
        "dns_v4_first": prefer_v4_proxy,
        "maas_proxy_port": maas_proxy_port,
    }

    formatted_peers = []
    for peer in peer_proxies:
        formatted_peers.append({
            "address": urlparse(peer).hostname,
            "port": urlparse(peer).port
        })
    context["peers"] = formatted_peers

    template_path = locate_template("proxy", MAAS_PROXY_CONF_TEMPLATE)
    template = tempita.Template.from_filename(template_path, encoding="UTF-8")
    try:
        content = template.substitute(context)
    except NameError as error:
        raise ProxyConfigFail(*error.args)

    # Squid prefers ascii.
    content = content.encode("ascii")
    target_path = get_proxy_config_path()
    atomic_write(content, target_path, overwrite=True, mode=0o644)
Exemplo n.º 9
0
    def _configure(self, upstream_http):
        """Update the HTTP configuration for the rack."""
        template = load_template("http", "rackd.nginx.conf.template")
        try:
            rendered = template.substitute({
                "upstream_http":
                list(sorted(upstream_http)),
                "resource_root":
                self._resource_root,
                "machine_resources":
                os.path.join(snappy.get_snap_path(), "usr/share/maas") if
                (snappy.running_in_snap()) else "/usr/share/maas",
            })
        except NameError as error:
            raise HTTPConfigFail(*error.args)
        else:
            # The rendered configuration is Unicode text but should contain
            # only ASCII characters.
            rendered = rendered.encode("ascii")

        target_path = compose_http_config_path("rackd.nginx.conf")
        os.makedirs(os.path.dirname(target_path), exist_ok=True)
        atomic_write(rendered, target_path, overwrite=True, mode=0o644)
Exemplo n.º 10
0
 def test_get_snap_path_returns_None(self):
     self.patch(os, "environ", {})
     self.assertIsNone(snappy.get_snap_path())
Exemplo n.º 11
0
 def test_get_snap_path_returns_path(self):
     path = factory.make_name()
     self.patch(os, "environ", {"SNAP": path})
     self.assertEqual(path, snappy.get_snap_path())
Exemplo n.º 12
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()):
        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
Exemplo n.º 13
0
def get_resources_bin_path():
    """Return the path of the resources binary."""
    prefix = get_snap_path() or ""
    arch = get_architecture()
    return f"{prefix}/usr/share/maas/machine-resources/{arch}"