def action(self, nodename, thr=None, **kwargs): options = self.parse_options(kwargs) if options.catalog == "collector": if options.template is None: raise ex.HTTP(400, "template is not set") request_options = {"props": "tpl_definition"} try: data = shared.NODE.collector_rest_get( "/provisioning_templates/%s" % options.template, request_options) return data["data"][0]["tpl_definition"] except IndexError: raise ex.HTTP(404, "template not found") raise ex.HTTP(400, "unknown catalog %s" % options.catalog)
def action(self, nodename, thr=None, **kwargs): lock_id = self.lock_acquire(Env.nodename, "join", 30, thr=thr) if not lock_id: raise ex.HTTP(503, "Lock not acquired") with shared.JOIN_LOCK: data = self.join(nodename, thr=thr, **kwargs) self.lock_release("join", lock_id, thr=thr) return data
def action(self, nodename, thr=None, **kwargs): options = self.parse_options(kwargs) cf = "/etc/drbd.d/%s.res" % options.res if not os.path.exists(cf): raise ex.HTTP(404, "resource configuration file does not exist") with open(cf, "r") as f: buff = f.read() return {"data": buff}
def action(self, nodename, thr=None, stream_id=None, **kwargs): options = self.parse_options(kwargs) svc = thr.get_service(options.path) if svc is None: raise ex.HTTP(404, "%s not found" % options.path) logfile = os.path.join(svc.log_d, svc.name + ".log") ofile = thr._action_logs_open(logfile, options.backlog, svc.path) return thr.read_file_lines(ofile)
def action(self, nodename, thr=None, **kwargs): options = self.parse_options(kwargs) if options.kind == "node": obj = shared.NODE elif options.kind: obj = factory(options.kind)(name="dummy", node=shared.NODE, volatile=True) else: raise ex.HTTP(400, "A kind must be specified.") return obj.full_kwstore.dump()
def options_path(options, required=True): for key in ("path", "svcpath", "svcname"): try: return options[key] except KeyError: pass if required: raise ex.HTTP(400, "required option path is not set") return None
def rbac(self, nodename, thr=None, **kwargs): options = self.parse_options(kwargs) if options.template is not None: thr.rbac_requires(roles=["admin"], namespaces=[options.namespace], **kwargs) return if not options.data: return errors = self.rbac_create_data(payload=options.data, thr=thr, **kwargs) if errors: raise ex.HTTP(403, errors)
def get_option(data, opt): name = opt["name"] fmt = opt.get("format", "string") required = opt.get("required", False) if fmt != "object_path" and required and name not in data: raise ex.HTTP(400, "required option %s is not set" % name) value = data.get(name, opt.get("default")) if value is None: value = opt.get("default") try: value = getattr(utilities.converters, "convert_" + fmt)(value) except AttributeError: pass except Exception as exc: raise ex.HTTP( 400, "option %s format conversion to %s error: %s" % (name, fmt, exc)) if fmt == "object_path": value = options_path(data, required=required) return name, value
def rbac(self, nodename, thr=None, **kwargs): options = self.parse_options(kwargs) name, namespace, kind = split_path(options.path) if options.action in GUEST_ACTIONS: role = "guest" elif options.action in OPERATOR_ACTIONS: role = "operator" elif options.action in ADMIN_ACTIONS: role = "admin" else: role = "root" if options.action == "set": # load current config try: cf = shared.SERVICES[options.path].print_config_data() except Exception as exc: cf = {} # purge unwanted sections try: del cf["metadata"] except Exception: pass # merge changes in current config for buff in options.options.get("kw", []): k, v = buff.split("=", 1) if k[-1] in ("+", "-"): k = k[:-1] k = k.strip() try: s, k = k.split(".", 1) except Exception: s = "DEFAULT" if s not in cf: cf[s] = {} cf[s][k] = v # apply object create rbac to the amended config payload = {options.path: cf} errors = self.rbac_create_data(payload=payload, thr=thr, **kwargs) if errors: raise ex.HTTP(403, errors) else: thr.rbac_requires(roles=[role], namespaces=[namespace], **kwargs) if options.cmd: # compat, requires root kwargs["roles"] = ["root"] thr.rbac_requires(**kwargs)
def action(self, nodename, thr=None, **kwargs): options = self.parse_options(kwargs) timeout = options.timeout if options.timeout and options.timeout < MAX_TIMEOUT else MAX_TIMEOUT if not which("gotty"): raise ex.HTTP(500, "The gotty executable is not installed") creds = "user:"******"private_key") cert_chain = os.path.join(Env.paths.certs, "certificate_chain") cmd = [ "gotty", "--port", "0", "--random-url", "--tls", "--tls-crt", cert_chain, "--tls-key", private_key, "--timeout", str(timeout), "--once", "--ws-origin", ".*", "--permit-write", "om", options.path, "enter", "--rid", options.rid, ] env = dict(os.environ).update({ "GOTTY_CREDENTIAL": creds, }) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) thr.parent.push_proc(proc) for line in iter(proc.stderr.readline, ""): line = try_decode(line) if "https://" not in line: continue url = line.split("https://::", 1)[-1].strip() url = "https://" + creds + "@" + Env.nodename + url return {"data": {"url": url}}
def action(self, nodename, thr=None, stream_id=None, **kwargs): options = self.parse_options(kwargs) svc = thr.get_service(options.path) if svc is None: raise ex.HTTP(404, "%s not found" % options.path) request_headers = HTTPHeaderMap( thr.streams[stream_id]["request"].headers) try: content_type = bdecode(request_headers.get("accept").pop()) except: content_type = "application/json" thr.streams[stream_id]["content_type"] = content_type logfile = os.path.join(svc.log_d, svc.name + ".log") ofile = thr._action_logs_open(logfile, 0, svc.path) thr.streams[stream_id]["pushers"].append({ "o": self, "fn": "h2_push_logs", "args": [ofile, True], })
def action(self, nodename, thr=None, **kwargs): if "node.x.drbdadm" not in capabilities: raise ex.Error("this node is not drbd capable") out, err, ret = justcall(["drbdadm", "dump"]) if ret: raise ex.HTTP(500, err) minors = set() ports = set() for line in out.splitlines(): m = re.match(RE_MINOR, line) if m is not None: minors.add(int(m.group(1))) m = re.match(RE_PORT, line) if m is not None: ports.add(int(m.group(1))) return { "minors": sorted(list(minors)), "ports": sorted(list(ports)), }
def action(self, nodename, thr=None, **kwargs): options = self.parse_options(kwargs) name, namespace, kind = split_path(options.path) if thr.get_service(options.path) is None and options.action not in ("create", "deploy"): thr.log_request("service action (%s not installed)" % options.path, nodename, lvl="warning", **kwargs) raise ex.HTTP(404, "%s not found" % options.path) if not options.action and not options.cmd: thr.log_request("service action (no action set)", nodename, lvl="error", **kwargs) raise ex.HTTP(400, "action not set") for opt in ("node", "daemon", "svcs", "service", "s", "parm_svcs", "local", "id"): if opt in options.options: del options.options[opt] for opt, ropt in (("jsonpath_filter", "filter"),): if opt in options.options: options.options[ropt] = options.options[opt] del options.options[opt] options.options["local"] = True pmod = importlib.import_module("commands.{kind}.parser".format(kind=kind)) popt = pmod.OPT def find_opt(opt): for k, o in popt.items(): if o.dest == opt: return o if o.dest == "parm_" + opt: return o if options.cmd: cmd = [options.cmd] else: cmd = [options.action] for opt, val in options.options.items(): po = find_opt(opt) if po is None: continue if val == po.default: continue if val is None: continue opt = po._long_opts[0] if po._long_opts else po._short_opts[0] if po.action == "append": cmd += [opt + "=" + str(v) for v in val] elif po.action == "store_true" and val: cmd.append(opt) elif po.action == "store_false" and not val: cmd.append(opt) elif po.type == "string": opt += "=" + val cmd.append(opt) elif po.type == "integer": opt += "=" + str(val) cmd.append(opt) fullcmd = Env.om + ["svc", "-s", options.path] + cmd thr.log_request("run 'om %s %s'" % (options.path, " ".join(cmd)), nodename, **kwargs) if options.sync: proc = Popen(fullcmd, stdout=PIPE, stderr=PIPE, stdin=None, close_fds=True) out, err = proc.communicate() try: result = json.loads(out) except Exception: result = { "status": 0, "data": { "out": bdecode(out), "err": bdecode(err), "ret": proc.returncode, }, } else: import uuid session_id = str(uuid.uuid4()) env = {} env.update(os.environ) env["OSVC_PARENT_SESSION_UUID"] = session_id proc = Popen(fullcmd, stdin=None, close_fds=True, env=env) thr.push_proc(proc) result = { "status": 0, "data": { "pid": proc.pid, "session_id": session_id, }, "info": "started %s action %s" % (options.path, " ".join(cmd)), } return result
def action(self, nodename, thr=None, **kwargs): options = self.parse_options(kwargs) name, namespace, kind = split_path(options.path) if thr.get_service(options.path) is None and options.action not in ( "create", "deploy"): thr.log_request("service action (%s not installed)" % options.path, nodename, lvl="warning", **kwargs) raise ex.HTTP(404, "%s not found" % options.path) if not options.action and not options.cmd: thr.log_request("service action (no action set)", nodename, lvl="error", **kwargs) raise ex.HTTP(400, "action not set") for opt in ("node", "daemon", "svcs", "service", "s", "parm_svcs", "local", "id"): if opt in options.options: del options.options[opt] for opt, ropt in (("jsonpath_filter", "filter"), ): if opt in options.options: options.options[ropt] = options.options[opt] del options.options[opt] options.options["local"] = True if options.cmd: cmd = [options.cmd] else: pmod = importlib.import_module( "commands.{kind}.parser".format(kind=kind)) cmd = get_action_args_from_parser(pmod.OPT, options.action, options) fullcmd = Env.om + ["svc", "-s", options.path] + cmd thr.log_request("run 'om %s %s'" % (options.path, " ".join(cmd)), nodename, **kwargs) if options.sync: proc = Popen(fullcmd, stdout=PIPE, stderr=PIPE, stdin=None, close_fds=True) out, err = proc.communicate() try: result = json.loads(out) except Exception: result = { "status": 0, "data": { "out": bdecode(out), "err": bdecode(err), "ret": proc.returncode, }, } else: import uuid session_id = str(uuid.uuid4()) env = {} env.update(os.environ) env["OSVC_PARENT_SESSION_UUID"] = session_id proc = Popen(fullcmd, stdin=None, close_fds=True, env=env) thr.parent.push_proc(proc, cmd=fullcmd, session_id=session_id) result = { "status": 0, "data": { "pid": proc.pid, "session_id": session_id, }, "info": "started %s action %s" % (options.path, " ".join(cmd)), } return result