Пример #1
0
 def ack_unit_attention(self, d):
     if not os.path.exists(d):
         return 0
     i = self.preempt_timeout
     self.set_read_only(0)
     while i > 0:
         i -= 1
         cmd = ['sg_persist', '-n', '-r', d]
         p = Popen(cmd, stdout=PIPE, stderr=PIPE, close_fds=True)
         out, err = p.communicate()
         out = bdecode(out)
         err = bdecode(err)
         ret = p.returncode
         if "unsupported service action" in err:
             raise ex.excScsiPrNotsupported(
                 "disk %s does not support persistent reservation" % d)
         if "error opening file" in err:
             return 0
         if "Unit Attention" in out or ret != 0:
             self.log.debug("disk %s reports 'Unit Attention' ... waiting" %
                            d)
             time.sleep(1)
             continue
         break
     if i == 0:
         self.log.error(
             "timed out waiting for 'Unit Attention' to go away on disk %s"
             % d)
         return 1
     return 0
Пример #2
0
 def _fullpem(self):
     required = set(["private_key", "certificate_chain"])
     if required & set(self.data_keys()) != required:
         self.gen_cert()
     buff = bdecode(self.decode_key("private_key"))
     buff += bdecode(self.decode_key("certificate_chain"))
     return buff
Пример #3
0
 def encrypt(self, data, cluster_name=None, secret=None, encode=True):
     """
     Encrypt and return data in a wrapping structure.
     """
     if cluster_name is None:
         cluster_name = self.cluster_name
     if secret is None:
         cluster_key = self.cluster_key
     else:
         cluster_key = secret
     if cluster_key is None:
         return
     iv = self.gen_iv()
     try:
         data = json.dumps(data).encode()
     except (UnicodeDecodeError, TypeError):
         # already binary data
         pass
     message = {
         "clustername":
         cluster_name,
         "nodename":
         rcEnv.nodename,
         "iv":
         bdecode(base64.urlsafe_b64encode(iv)),
         "data":
         bdecode(
             base64.urlsafe_b64encode(self._encrypt(data, cluster_key,
                                                    iv))),
     }
     if encode:
         return (json.dumps(message) + '\0').encode()
     return json.dumps(message)
Пример #4
0
 def decrypt(self, message, cluster_name=None, secret=None, sender_id=None):
     """
     Validate the message meta, decrypt and return the data.
     """
     if cluster_name is None:
         cluster_names = self.cluster_names
     else:
         cluster_names = [cluster_name]
     message = bdecode(message).rstrip("\0\x00")
     try:
         message = json.loads(message)
     except ValueError:
         message_len = len(message)
         if message_len > 40:
             self.log.error("misformatted encrypted message from %s: %s",
                            sender_id, message[:30] + "..." + message[-10:])
         elif message_len > 0:
             self.log.error("misformatted encrypted message from %s",
                            sender_id)
         return None, None, None
     msg_clustername = message.get("clustername")
     msg_nodename = message.get("nodename")
     if secret is None:
         if msg_nodename in self.cluster_drpnodes:
             cluster_key = self.get_secret(Storage(server=msg_nodename),
                                           None)
         else:
             cluster_key = self.cluster_key
     else:
         cluster_key = secret
     if cluster_name != "join" and \
        msg_clustername not in set(["join"]) | self.cluster_names:
         self.log.warning("discard message from cluster %s, sender %s",
                          msg_clustername, sender_id)
         return None, None, None
     if cluster_key is None:
         return None, None, None
     if msg_nodename is None:
         return None, None, None
     iv = message.get("iv")
     if iv is None:
         return None, None, None
     if self.blacklisted(sender_id):
         return None, None, None
     iv = base64.urlsafe_b64decode(to_bytes(iv))
     data = base64.urlsafe_b64decode(to_bytes(message["data"]))
     try:
         data = self._decrypt(data, cluster_key, iv)
     except Exception as exc:
         self.log.error("decrypt message from %s: %s", msg_nodename,
                        str(exc))
         self.blacklist(sender_id)
         return None, None, None
     if sender_id:
         self.blacklist_clear(sender_id)
     try:
         return msg_clustername, msg_nodename, json.loads(bdecode(data))
     except ValueError as exc:
         return msg_clustername, msg_nodename, data
Пример #5
0
    def provisioner(self):
        if which("mdadm") is None:
            raise ex.excError("mdadm is not installed")

        level = self.r.oget("level")
        devs = self.r.oget("devs")
        spares = self.r.oget('spares')
        chunk = self.r.oget("chunk")
        layout = self.r.oget("layout")

        if len(devs) == 0:
            raise ex.excError(
                "at least 2 devices must be set in the 'devs' provisioning parameter"
            )

        # long md names cause a buffer overflow in mdadm
        name = self.r.devname()
        cmd = [
            self.r.mdadm, '--create', name, '--force', '--quiet',
            '--metadata=default'
        ]
        cmd += ['-n', str(len(devs) - spares)]
        if level:
            cmd += ["-l", level]
        if spares:
            cmd += ["-x", str(spares)]
        if chunk:
            cmd += ["-c", str(convert_size(chunk, _to="k", _round=4))]
        if layout:
            cmd += ["-p", layout]
        cmd += devs
        self.r.log.info(" ".join(cmd))
        from subprocess import Popen, PIPE
        proc = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
        out, err = proc.communicate(input=b'no\n')
        out, err = bdecode(out).strip(), bdecode(err).strip()
        self.r.log.info(out)
        if proc.returncode != 0:
            raise ex.excError(err)
        self.r.can_rollback = True
        if len(out) > 0:
            self.r.log.info(out)
        if len(err) > 0:
            self.r.log.error(err)
        self.r.uuid = os.path.basename(name)
        uuid = self.get_real_uuid(name)
        self.r.uuid = uuid
        if self.r.shared:
            self.r.log.info("set %s.uuid = %s", self.r.rid, uuid)
            self.r.svc._set(self.r.rid, "uuid", uuid)
        else:
            self.r.log.info("set %s.uuid@%s = %s", self.r.rid, rcEnv.nodename,
                            uuid)
            self.r.svc._set(self.r.rid, "uuid@" + rcEnv.nodename, uuid)
        self.r.svc.node.unset_lazy("devtree")
Пример #6
0
 def get_secret(self, sp, secret):
     if want_context():
         return
     if sp.context and not sp.context.get("secret"):
         return
     elif secret:
         return bdecode(secret)
     elif sp.server in self.cluster_drpnodes:
         node = self.get_node()
         return bdecode(
             self.prepare_key(
                 node.oget("cluster", "secret", impersonate=sp.server)))
     else:
         return bdecode(self.cluster_key)
Пример #7
0
 def action(self, nodename, thr=None, **kwargs):
     options = self.parse_options(kwargs)
     if not options.data and not options.template:
         return {"status": 0, "info": "no data"}
     if options.template is not None:
         if options.path:
             paths = [options.path]
             cmd = [
                 "create", "-s", options.path,
                 "--template=%s" % options.template, "--env=-"
             ]
         else:
             paths = [p for p in options.data]
             cmd = ["create", "--template=%s" % options.template, "--env=-"]
     else:
         paths = [p for p in options.data]
         cmd = ["create", "--config=-"]
     validate_paths(paths)
     if options.namespace:
         cmd.append("--namespace=" + options.namespace)
     if options.restore:
         cmd.append("--restore")
     thr.log_request("create/update %s" % ",".join(paths), nodename,
                     **kwargs)
     proc = thr.service_command(None,
                                cmd,
                                stdout=PIPE,
                                stderr=PIPE,
                                stdin=json.dumps(options.data))
     if options.sync:
         out, err = proc.communicate()
         result = {
             "status": proc.returncode,
             "data": {
                 "out": bdecode(out),
                 "err": bdecode(err),
                 "ret": proc.returncode,
             },
         }
     else:
         thr.push_proc(proc)
         result = {
             "status": 0,
             "info": "started %s action %s" % (options.path, " ".join(cmd)),
         }
     if options.provision:
         for path in paths:
             thr.set_smon(path, global_expect="provisioned")
     return result
Пример #8
0
 def _add_key(self, key, data):
     if not key:
         raise ex.excError("configuration key name can not be empty")
     if not data:
         raise ex.excError("configuration value can not be empty")
     if not is_string(data):
         data = "base64:"+bdecode(base64.urlsafe_b64encode(data))
     elif "\n" in data:
         data = "base64:"+bdecode(base64.urlsafe_b64encode(bencode(data)))
     else:
         data = "literal:"+data
     self.set_multi(["data.%s=%s" % (key, data)])
     self.log.info("configuration key '%s' added (%s)", key, print_size(len(data), compact=True, unit="b"))
     # refresh if in use
     self.postinstall(key)
Пример #9
0
 def read_slot(self, slot, fo=None):
     offset = self.slot_offset(slot)
     fo.seek(offset, os.SEEK_SET)
     fo.readinto(self.slot_buff)
     data = bdecode(self.slot_buff[:])
     end = data.index("\0")
     return data[:end]
Пример #10
0
 def post(self, uri, data=None):
     api = self.api+uri+"/"
     headers = {'Content-Type': 'application/json'}
     if data:
         data = json.dumps(data)
     r = requests.post(api, data=data, auth=self.auth, timeout=self.timeout, verify=VERIFY, headers=headers)
     return bdecode(r.content)
Пример #11
0
 def meta_read_slot(self, slot, fo=None):
     offset = self.meta_slot_offset(slot)
     fo.seek(offset, os.SEEK_SET)
     fo.readinto(self.meta_slot_buff)
     try:
         return bdecode(self.meta_slot_buff[:mmap.PAGESIZE])
     except Exception as exc:
         return None
Пример #12
0
def is_container():
    p = '/proc/1/environ'
    if not os.path.exists(p):
        return False
    with open(p, 'r') as f:
        buff = f.read()
    if "container=lxc" in bdecode(buff):
        return True
    return False
Пример #13
0
 def _pkcs12(self, password):
     required = set(["private_key", "certificate_chain"])
     if required & set(self.data_keys()) != required:
         self.gen_cert()
     from subprocess import Popen, PIPE
     import tempfile
     _tmpcert = tempfile.NamedTemporaryFile()
     _tmpkey = tempfile.NamedTemporaryFile()
     tmpcert = _tmpcert.name
     tmpkey = _tmpkey.name
     _tmpcert.close()
     _tmpkey.close()
     if password is None:
         from getpass import getpass
         pwd = getpass("Password: "******"\n"
     elif password in ["/dev/stdin", "-"]:
         pwd = sys.stdin.readline()
     else:
         pwd = password + "\n"
     if six.PY3:
         pwd = bencode(pwd)
     try:
         with open(tmpkey, "w") as _tmpkey:
             os.chmod(tmpkey, 0o600)
             _tmpkey.write(bdecode(self.decode_key("private_key")))
         with open(tmpcert, "w") as _tmpcert:
             os.chmod(tmpcert, 0o600)
             _tmpcert.write(bdecode(self.decode_key("certificate_chain")))
         cmd = [
             "openssl", "pkcs12", "-export", "-in", tmpcert, "-inkey",
             tmpkey, "-passout", "stdin"
         ]
         proc = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
         out, err = proc.communicate(input=pwd)
         if err:
             print(err, file=sys.stderr)
         return out
     finally:
         if os.path.exists(tmpcert):
             os.unlink(tmpcert)
         if os.path.exists(tmpkey):
             os.unlink(tmpkey)
Пример #14
0
 def h2_daemon_stream_fetch(self, stream_id, conn):
     resps = []
     for push in conn.get_pushes(stream_id):
         resps.append(push.get_response())
     for resp in resps:
         # resp.read() can modify push.promises_headers, which get_pushes iterates
         # causing a RuntimeError => keep in a separate loop
         evt = resp.read()
         evt = json.loads(bdecode(evt))
         yield evt
Пример #15
0
 def post2(self, uri, data=None):
     api = self.api.replace("api/v1.0", "")+uri
     s = requests.Session()
     r = s.get(api)
     csrf_token = r.cookies['csrftoken']
     data["csrfmiddlewaretoken"] = csrf_token
     if data:
         data = json.dumps(data)
     r = requests.post(api, data=data, auth=self.auth, timeout=self.timeout, verify=VERIFY)
     return bdecode(r.content)
Пример #16
0
 def parse_rsync(self, buff):
     """
     Extract normalized speed and transfered data size from the dd output
     """
     data = {"bytes": 0, "speed": 0}
     for line in bdecode(buff).splitlines():
         if line.startswith("Total bytes sent"):
             data["bytes"] = int(line.split()[-1].replace(",",""))
         elif line.endswith("/sec"):
             data["speed"] = int(convert_speed(line.split()[-2].replace(",","")+"/s"))
     return data
Пример #17
0
 def do_it(self, send_cmd, receive_cmd, node):
     self.log.info(' '.join(send_cmd + ["|"] + receive_cmd))
     p1 = Popen(send_cmd, stdout=PIPE)
     pi = Popen(["dd", "bs=4096"],
                stdin=p1.stdout,
                stdout=PIPE,
                stderr=PIPE)
     p2 = Popen(receive_cmd, stdin=pi.stdout, stdout=PIPE, stderr=PIPE)
     buff = p2.communicate()
     if p2.returncode == 0:
         stats_buff = pi.communicate()[1]
         stats = self.parse_dd(stats_buff)
         self.update_stats(stats, target=node)
     out = bdecode(buff[0])
     err = bdecode(buff[1])
     if p2.returncode != 0:
         if err is not None and len(err) > 0:
             self.log.error(err)
         raise ex.excError("sync failed")
     if out is not None and len(out) > 0:
         self.log.info(out)
Пример #18
0
 def parse_dd(self, buff):
     """
     Extract normalized speed and transfered data size from the dd output
     """
     data = {}
     if not buff:
         return data
     words = bdecode(buff).split()
     if "bytes" in words:
         data["bytes"] = int(words[words.index("bytes") - 1])
     if words[-1].endswith("/s"):
         data["speed"] = int(convert_speed("".join(words[-2:])))
     return data
Пример #19
0
 def h2_daemon_request(self,
                       data,
                       server=None,
                       node=None,
                       with_result=True,
                       silent=False,
                       cluster_name=None,
                       secret=None,
                       timeout=0,
                       sp=None,
                       method="GET"):
     secret = self.get_secret(sp, secret)
     path = self.h2_path_from_data(data)
     headers = self.h2_headers(node=node,
                               secret=secret,
                               multiplexed=data.get("multiplexed"),
                               af=sp.af)
     body = self.h2_body_from_data(data)
     headers.update({"Content-Length": str(len(body))})
     conn = self.h2c(sp=sp)
     elapsed = 0
     while True:
         try:
             conn.request(method, path, headers=headers, body=body)
             break
         except AssertionError as exc:
             raise ex.excError(str(exc))
         except ConnectionResetError:
             return {
                 "status": 1,
                 "error": "%s %s connection reset" % (method, path)
             }
         except (ConnectionRefusedError, ssl.SSLError, socket.error) as exc:
             try:
                 errno = exc.errno
             except AttributeError:
                 errno = None
             if errno in RETRYABLE and \
                (timeout == 0 or elapsed < timeout):
                 # Resource temporarily unavailable (busy, overflow)
                 # Retry after a delay, if the daemon is still
                 # running and timeout is not exhausted
                 time.sleep(PAUSE)
                 elapsed += PAUSE
                 continue
             return {"status": 1, "error": "%s" % exc}
     resp = conn.get_response()
     data = resp.read()
     data = json.loads(bdecode(data))
     return data
Пример #20
0
 def get_src_dir_dev(self, dev):
     """Given a directory path, return its hosting device
     """
     if dev in self.src_dir_devs_cache:
         return self.src_dir_devs_cache[dev]
     p = Popen(self.df_one_cmd + [dev], stdout=PIPE, stderr=STDOUT, close_fds=True)
     out, err = p.communicate()
     if p.returncode != 0:
         return
     out = bdecode(out).lstrip()
     lines = out.splitlines()
     if len(lines) == 2:
         out = lines[1]
     self.src_dir_devs_cache[dev] = out.split()[0]
     return self.src_dir_devs_cache[dev]
Пример #21
0
 def action(self, nodename, thr=None, stream_id=None, **kwargs):
     logfile = os.path.join(rcEnv.paths.pathlog, "node.log")
     ofile = thr._action_logs_open(logfile, 0, "node")
     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
     thr.streams[stream_id]["pushers"].append({
         "o": self,
         "fn": "h2_push_logs",
         "args": [ofile, True],
     })
Пример #22
0
 def action(self, nodename, thr=None, **kwargs):
     options = self.parse_options(kwargs)
     try:
         return {
             "status":
             0,
             "data":
             bdecode(shared.SERVICES[options.path].decode_key(options.key))
         }
     except ex.excError as exc:
         return {"status": 1, "error": str(exc)}
     except Exception as exc:
         return {
             "status": 1,
             "error": str(exc),
             "traceback": traceback.format_exc()
         }
Пример #23
0
 def action(self, nodename, thr=None, stream_id=None, **kwargs):
     options = self.parse_options(kwargs)
     thr.selector = options.selector
     if not thr.event_queue:
         thr.event_queue = queue.Queue()
     if options.full:
         data = thr.daemon_status()
         namespaces = thr.get_namespaces()
         fevent = {
             "nodename":
             rcEnv.nodename,
             "ts":
             time.time(),
             "kind":
             "full",
             "data":
             thr.filter_daemon_status(data,
                                      namespaces=namespaces,
                                      selector=options.selector),
         }
         if thr.h2conn:
             _msg = fevent
         elif thr.encrypted:
             _msg = thr.encrypt(fevent)
         else:
             _msg = thr.msg_encode(fevent)
         thr.event_queue.put(_msg)
     if not thr in thr.parent.events_clients:
         thr.parent.events_clients.append(thr)
     if not stream_id in thr.events_stream_ids:
         thr.events_stream_ids.append(stream_id)
     if thr.h2conn:
         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
         thr.streams[stream_id]["pushers"].append({
             "fn":
             "h2_push_action_events",
         })
     else:
         thr.raw_push_action_events()
Пример #24
0
 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 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],
     })
Пример #25
0
    def _handle_client(self, conn, cr, cw):
        chunks = []
        buff_size = 4096
        while True:
            try:
                data = cr.readline()
            except socket.timeout as exc:
                break
            except socket.error as exc:
                self.log.info("%s", exc)
                break
            if len(data) == 0:
                #self.log.info("no more data")
                break

            self.log.debug("received %s", data)

            try:
                data = bdecode(data)
                data = json.loads(data)
            except Exception as exc:
                self.log.error(exc)
                data = None

            if self.stopped():
                self.log.info("stop event received (handler thread)")
                break

            if data is None or not isinstance(data, dict):
                continue

            result = self.router(data)
            if result is not None:
                message = json.dumps(result) + "\n"
                cw.write(message)
                cw.flush()
                self.log.debug("replied %s", message)
                message_len = len(message)
                self.stats.sessions.tx += message_len
Пример #26
0
    def gen_cert(self):
        data = {}
        for key in ("cn", "c", "st", "l", "o", "ou", "email", "alt_names",
                    "bits", "validity", "ca"):
            val = self.oget("DEFAULT", key)
            if val is not None:
                data[key] = val

        ca = data.get("ca")
        casec = None
        if ca is not None:
            casecname, canamespace, _ = split_path(ca)
            casec = factory("sec")(casecname,
                                   namespace=canamespace,
                                   log=self.log,
                                   volatile=True)
            if not casec.exists():
                raise ex.excError("ca secret %s does not exist" % ca)

        for key in ("crt", "key", "csr"):
            data[key] = self.tempfilename()

        if "alt_names" in data:
            data["cnf"] = self.tempfilename()

        try:
            if casec:
                for key, kw in (("cacrt", "certificate"), ("cakey",
                                                           "private_key")):
                    if kw not in casec.data_keys():
                        continue
                    data[key] = self.tempfilename()
                    buff = bdecode(casec.decode_key(kw))
                    with open(data[key], "w") as ofile:
                        ofile.write(buff)
            gen_cert(log=self.log, **data)
            self._add("private_key", value_from=data["key"])
            if data.get("crt") is not None:
                self._add("certificate", value_from=data["crt"])
            if data.get("csr") is not None:
                self._add("certificate_signing_request",
                          value_from=data["csr"])
            if data.get("cakey") is None:
                self._add("certificate_chain", value_from=data["crt"])
            else:
                # merge cacrt and crt
                chain = self.tempfilename()
                try:
                    with open(data["crt"], "r") as ofile:
                        buff = ofile.read()
                    with open(data["cacrt"], "r") as ofile:
                        buff += ofile.read()
                    with open(chain, "w") as ofile:
                        ofile.write(buff)
                    self._add("certificate_chain", value_from=chain)
                finally:
                    try:
                        os.unlink(chain)
                    except Exception:
                        pass
            self.add_key("fullpem", self._fullpem())
        finally:
            for key in ("crt", "key", "cacrt", "cakey", "csr", "cnf"):
                if key not in data:
                    continue
                try:
                    os.unlink(data[key])
                except Exception:
                    pass
Пример #27
0
    def provisioner(self):
        if not which('vgdisplay'):
            self.r.log.error("vgdisplay command not found")
            raise ex.excError

        if not which('lvcreate'):
            self.r.log.error("lvcreate command not found")
            raise ex.excError

        if not which('lvdisplay'):
            self.r.log.error("lvdisplay command not found")
            raise ex.excError

        dev = self.get_dev()

        try:
            self.size = self.r.conf_get("size")
            self.size = str(self.size).upper()
            if "%" not in self.size:
                size_parm = ["-L", str(convert_size(self.size, _to="m")) + 'M']
            else:
                size_parm = ["-l", self.size]
            vg = self.r.conf_get("vg")
        except Exception as e:
            self.r.log.info("skip lv provisioning: %s" % str(e))
            return

        create_options = self.r.oget("create_options")
        cmd = ['vgdisplay', vg]
        out, err, ret = justcall(cmd)
        if ret != 0:
            self.r.log.error("volume group %s does not exist" % vg)
            raise ex.excError

        lvname = os.path.basename(dev)

        # create the logical volume
        cmd = ['lvcreate', '-n', lvname] + size_parm + create_options + [vg]
        _cmd = "yes | " + " ".join(cmd)
        self.r.log.info(_cmd)
        p1 = Popen(["yes"], stdout=PIPE, preexec_fn=restore_signals)
        p2 = Popen(cmd,
                   stdout=PIPE,
                   stderr=PIPE,
                   stdin=p1.stdout,
                   close_fds=True)
        out, err = p2.communicate()
        out = bdecode(out)
        err = bdecode(err)
        if p2.returncode != 0:
            raise ex.excError(err)
        if hasattr(self.r, "fullname"):
            self.r.can_rollback = True
        if len(out) > 0:
            for line in out.splitlines():
                self.r.log.info(line)
        if len(err) > 0:
            for line in err.splitlines():
                if line.startswith("WARNING:"):
                    self.r.log.warning(line.replace("WARNING: ", ""))
                else:
                    self.r.log.error(err)

        # /dev/mapper/$vg-$lv and /dev/$vg/$lv creation is delayed ... refresh
        try:
            cmd = [rcEnv.syspaths.dmsetup, 'mknodes']
            p = Popen(cmd, stdout=PIPE, stderr=PIPE)
            p.communicate()
        except:
            # best effort
            pass
        mapname = "%s-%s" % (vg.replace('-', '--'), lvname.replace('-', '--'))
        dev = '/dev/mapper/' + mapname

        for i in range(3, 0, -1):
            if os.path.exists(dev):
                break
            if i != 0:
                time.sleep(1)
        if i == 0:
            self.r.log.error("timed out waiting for %s to appear" % dev)
            raise ex.excError

        self.r.svc.node.unset_lazy("devtree")
Пример #28
0
    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 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 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 = __import__(kind + "mgr_parser")
        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 = rcEnv.python_cmd + [
            os.path.join(rcEnv.paths.pathlib, kind + "mgr.py"), "-s",
            options.path
        ] + cmd
        thr.log_request("run '%s'" % " ".join(fullcmd), 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:
            proc = Popen(fullcmd, stdin=None, close_fds=True)
            thr.push_proc(proc)
            result = {
                "status": 0,
                "info": "started %s action %s" % (options.path, " ".join(cmd)),
            }
        return result
Пример #29
0
 def msg_decode(self, message):
     message = bdecode(message).rstrip("\0\x00")
     if len(message) == 0:
         return
     return json.loads(message)
Пример #30
0
 def get(self, uri, params=None):
     r = requests.get(self.api+uri+"/?format=json", params=params, auth=self.auth, timeout=self.timeout, verify=VERIFY)
     return bdecode(r.content)