示例#1
0
    def recover_node(self, node_id, deliver):
        if not node_id in self.nodes:
            raise ChistributedException("No such node: {}".format(node_id))

        n = self.nodes[node_id]

        if n.state != Node.STATE_PARTITIONED:
            raise ChistributedException(
                "Node {} is not in a failed state".format(node_id))

        self.remove_partition(self.__failed_node_partition_name(node_id),
                              deliver)

        n.set_state(Node.STATE_RUNNING)
示例#2
0
    def from_dict(msg):
        def check_field(d, f):
            if not f in d:
                raise ChistributedException(
                    "Message does not have '%s' field: %s" % (f, msg))

        check_field(msg, "type")

        if msg["type"] in ("get", "set"):
            check_field(msg, "destination")
            check_field(msg, "key")

        if msg["type"] == "set":
            check_field(msg, "value")

        if msg["type"] in ("get", "getResponse", "set", "setResponse"):
            check_field(msg, "id")

        if msg["type"] in ("getResponse", "setResponse"):
            if not (("key" in msg and "value" in msg) or ("error" in msg)):
                raise ChistributedException(
                    "set/get response does not have error or key/value fields: %s"
                    % msg)

            if "error" in msg and "key" in msg and "value" in msg:
                raise ChistributedException(
                    "set/get response has both error and key/value fields: %s"
                    % msg)

        if msg["type"] not in ("get", "getResponse", "set", "setResponse"):
            check_field(msg, "destination")

        if msg["type"] == "get":
            return GetRequestMessage(msg["destination"], msg["id"], msg["key"])
        elif msg["type"] == "set":
            return SetRequestMessage(msg["destination"], msg["id"], msg["key"],
                                     msg["value"])
        elif msg["type"] == "getResponse" and ("key" in msg
                                               and "value" in msg):
            return GetResponseOKMessage(msg["id"], msg["key"], msg["value"])
        elif msg["type"] == "getResponse" and "error" in msg:
            return GetResponseErrorMessage(msg["id"], msg["error"])
        elif msg["type"] == "setResponse" and ("key" in msg
                                               and "value" in msg):
            return SetResponseOKMessage(msg["id"], msg["key"], msg["value"])
        elif msg["type"] == "setResponse" and "error" in msg:
            return SetResponseErrorMessage(msg["id"], msg["error"])
        else:
            return CustomMessage(msg["type"], msg["destination"], msg)
示例#3
0
    def start_node(self, node_id, extra_params=[]):
        '''
        Start a node with given name and parameters.

        Note all output will be sent to /dev/null (or the platform's equivalent).

        Highly unsafe of course.
        '''
        args = self.node_executable[:]

        args += [
            '--node-name', node_id, '--pub-endpoint', self.pub_endpoint,
            '--router-endpoint', self.router_endpoint
        ]

        args += extra_params

        if self.debug:
            stdout = None
            stderr = None
        else:
            if self.devnull is None:
                self.devnull = open(os.devnull, "w")
            stdout = self.devnull
            stderr = self.devnull

        try:
            proc = subprocess.Popen(args, stdout=stdout, stderr=stderr)
            self.node_pids[node_id] = proc
        except OSError, ose:
            raise ChistributedException(
                "Could not start node process. Tried to run '%s'" %
                " ".join(args),
                original_exception=ose)
示例#4
0
    def start_node(self, node_id, extra_params=[]):
        if not node_id in self.nodes:
            raise ChistributedException("No such node: {}".format(node_id))

        self.nodes[node_id].set_state(Node.STATE_STARTING)

        self.backend.start_node(node_id, extra_params)
示例#5
0
    def from_json(s):
        msg = json.loads(s)

        if not isinstance(msg, dict):
            raise ChistributedException("Not a valid message: %s" % s)

        return Message.from_dict(msg)
示例#6
0
    def get_node_executable(self):
        v = self.config_values[Config.OPTION_NODE_EXECUTABLE]

        if v is None or len(v) == 0:
            raise ChistributedException("Option {} must have a value".format(
                Config.OPTION_NODE_EXECUTABLE))

        return v
示例#7
0
    def get_nodes(self):
        nodes = self.config_values[Config.OPTION_NODES]

        if nodes is None or len(nodes) == 0:
            raise ChistributedException("Option {} must have a value".format(
                Config.OPTION_NODES))

        return nodes.split()
示例#8
0
    def fail_node(self, node_id):
        if not node_id in self.nodes:
            raise ChistributedException("No such node: {}".format(node_id))

        n = self.nodes[node_id]

        if n.state == Node.STATE_PARTITIONED:
            raise ChistributedException(
                "Node {} is already in a failed state".format(node_id))

        if n.state != Node.STATE_RUNNING:
            raise ChistributedException(
                "Node {} cannot be failed because it is not running".format(
                    node_id))

        self.add_partition(self.__failed_node_partition_name(node_id),
                           [node_id])

        n.set_state(Node.STATE_PARTITIONED)
示例#9
0
    def wait_for_state(self, state):
        self.cv.acquire()
        while self.state not in (state, Node.STATE_FAILED):
            self.cv.wait()
        self.cv.release()

        if self.state != state:
            raise ChistributedException(
                "Node entered failed state while waiting for state %s" %
                Node.state_str[state])
示例#10
0
    def wait_for_get_set_response(self, msg_id):
        self.requests_cv_lock.acquire()

        if not msg_id in self.processed_requests and not msg_id in self.pending_requests:
            self.requests_cv_lock.release()
            raise ChistributedException("No such set/get request: %i" % msg_id)

        while msg_id not in self.processed_requests:
            self.requests_cv.wait()
        self.requests_cv_lock.release()
示例#11
0
    def get_config_file_values(config_file):
        if not os.path.exists(config_file):
            return {}

        with open(config_file, 'r') as f:
            config_file_values = yaml.safe_load(f)

        if type(config_file_values) != dict:
            raise ChistributedException("{} is not valid YAML".format(f))

        return config_file_values
示例#12
0
    def add_partition(self, name, nodes1, nodes2=None):
        if name in self.partitions:
            raise ChistributedException(
                "A partition named '%s' already exists" % name)

        for n in nodes1:
            if n not in self.nodes:
                raise ChistributedException("No such node: %s" % n)

        if nodes2 is None:
            nodes2 = [n for n in self.nodes if n not in nodes1]
        else:
            for n in nodes2:
                if n not in self.nodes:
                    raise ChistributedException("No such node: %s" % n)

        p = Partition(name, [self.nodes[n] for n in nodes1],
                      [self.nodes[n] for n in nodes2])

        self.partitions[name] = p
示例#13
0
    def send_get_msg(self, node_id, key):
        if not node_id in self.nodes:
            raise ChistributedException("No such node: {}".format(node_id))

        msg = GetRequestMessage(node_id, self.next_id, key)

        self.pending_get_requests[self.next_id] = msg

        self.next_id += 1

        self.backend.send_message(node_id, msg)
示例#14
0
    def remove_partition(self, name, deliver):
        if name not in self.partitions:
            raise ChistributedException("No such partition: %s" % name)

        # Acquire lock to prevent messages being added to message queue
        # while we remove the partition
        self.msg_queue_lock.acquire()

        self.__process_partitioned_messages(self.partitions[name], deliver)

        del self.partitions[name]

        self.msg_queue_lock.release()
示例#15
0
    def get_config(cls, config_file, config_overrides={}):
        config = {}

        config_values = cls.get_config_file_values(config_file)
        config.update(config_values)
        config.update(config_overrides)

        for o in Config.REQUIRED_OPTIONS:
            if o not in config:
                raise ChistributedException(
                    "Configuration file %s does not include required option %s"
                    % (config_file, o))

        return cls(config)
示例#16
0
    def process_message(self, msg, source):
        if source is not None and source not in self.nodes:
            raise ChistributedException("No such node: {}".format(source))

        if isinstance(msg, (GetResponseOKMessage, GetResponseErrorMessage,
                            SetResponseOKMessage, SetResponseErrorMessage)):
            if isinstance(msg,
                          (GetResponseOKMessage, GetResponseErrorMessage)):
                pending = self.pending_get_requests.get(msg.id, None)
                msg_type = "GET"
            elif isinstance(msg,
                            (SetResponseOKMessage, SetResponseErrorMessage)):
                pending = self.pending_set_requests.get(msg.id, None)
                msg_type = "SET"

            if pending is None:
                s = colorama.Style.BRIGHT + colorama.Fore.YELLOW
                s += "WARNING: Received unexpected %s response id=%i" % (
                    msg_type, msg.id)
                s += colorama.Style.RESET_ALL
                print s
            else:
                msg_name = "%s id=%s" % (msg_type, msg.id)
                if isinstance(msg, GetResponseErrorMessage):
                    s = colorama.Style.BRIGHT + colorama.Fore.RED
                    s += "ERROR: %s failed (k=%s): %s" % (
                        msg_name, pending.key, msg.error)
                    s += colorama.Style.RESET_ALL
                    print s
                elif isinstance(msg, SetResponseErrorMessage):
                    s = colorama.Style.BRIGHT + colorama.Fore.RED
                    s += "ERROR: %s failed (%s=%s): %s" % (
                        msg_name, pending.key, pending.value, msg.error)
                    s += colorama.Style.RESET_ALL
                    print s
                elif isinstance(msg, GetResponseOKMessage):
                    if pending.key != msg.key:
                        s = colorama.Style.BRIGHT + colorama.Fore.YELLOW
                        s += "WARNING: %s response has unexpected key (got %s=%s, expected %s=%s" % (
                            msg_name, msg.key, msg.value, pending.key,
                            msg.value)
                        s += colorama.Style.RESET_ALL
                        print s
                    else:
                        s = colorama.Style.BRIGHT + colorama.Fore.GREEN
                        s += "%s OK: %s = %s" % (msg_name, msg.key, msg.value)
                        s += colorama.Style.RESET_ALL
                        print s
                elif isinstance(msg, SetResponseOKMessage):
                    if pending.key != msg.key or pending.value != msg.value:
                        s = colorama.Style.BRIGHT + colorama.Fore.YELLOW
                        s += "WARNING: %s response has unexpected values (got %s=%s, expected %s=%s" % (
                            msg_name, msg.key, msg.value, pending.key,
                            pending.value)
                        s += colorama.Style.RESET_ALL
                        print s
                    else:
                        s = colorama.Style.BRIGHT + colorama.Fore.GREEN
                        s += "%s OK: %s = %s" % (msg_name, msg.key, msg.value)
                        s += colorama.Style.RESET_ALL
                        print s

                if isinstance(msg,
                              (GetResponseOKMessage, GetResponseErrorMessage)):
                    del self.pending_get_requests[msg.id]
                elif isinstance(
                        msg, (SetResponseOKMessage, SetResponseErrorMessage)):
                    del self.pending_set_requests[msg.id]

        elif isinstance(msg, CustomMessage):
            msg.set_source(source)

            self.msg_queue_lock.acquire()
            self.msg_queue.appendleft(msg)
            self.msg_queue_lock.release()

            self.__process_queue()
示例#17
0
 def check_field(d, f):
     if not f in d:
         raise ChistributedException(
             "Message does not have '%s' field: %s" % (f, msg))