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
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())
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)
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)
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')
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)
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)
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)
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)
def test_get_snap_path_returns_None(self): self.patch(os, "environ", {}) self.assertIsNone(snappy.get_snap_path())
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())
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 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}"