Exemplo n.º 1
0
 def __configure_channels(self, args):
     if args.file is not None:
         with open(args.file) as f:
             config = f.read()
             config = json.loads(config)
             LOG.debug("json loaded %s", config)
     self.broadcaster.configure(config)
Exemplo n.º 2
0
    def test_broadcast(self, msg_data, config=None):
        if config is None:
            config = self.config
        if config is None:
            return self.broadcast(msg_data)

        msg = Message(None, msg_data, None)
        msg.time = time.time()
        msg.host = self.server_id

        server_config = config[str(self.server_id)]
        for c in self.channels:
            channel_config = server_config[str(c.channel_id)]
            if channel_config[0][0] == 0:
                LOG.info("skipping c%i at server %i", c.channel_id,
                         self.server_id)
                continue
            delay = channel_config[0][1]
            if delay > 0:
                LOG.info("add %i delay to c%i at server %i", delay,
                         c.channel_id, self.server_id)
                time.sleep(delay)
            for id, host in self.hosts.items():
                if id == self.server_id:
                    continue
                if channel_config[id + 1] == 0:
                    # continue
                    break
                c.send(host.ip, host.port, msg)
Exemplo n.º 3
0
    def kill(self):
        """terminate cluster"""

        for _, server in self.servers.items():
            server['log'].close()
            server['process'].kill()

        LOG.info('cluster killed')
Exemplo n.º 4
0
 def send_new_group(self, t):
     """ Sends a reconfigure request for the group consisting of the id """
     msg_dict = {'new_group': True, 'gid': t, 'id': self.host.id}
     msg_bytes = json.dumps(msg_dict).encode()
     msg_size = struct.pack('i', len(msg_bytes))
     LOG.debug("host%i sending new_group: %f", self.host.id, t)
     # LOG.debug("host%i sending new_group: %s", self.host.id, msg_bytes)
     self.atomic_b.broadcast(msg_size + msg_bytes)
Exemplo n.º 5
0
 def send(self, id, buf):
     if id not in self.servers:
         LOG.error("server %i does not exists", id)
         return False
     LOG.debug("sending %s to server %i", buf, id)
     buf += '\n'
     self.servers[id]['process'].stdin.write(buf.encode())
     self.servers[id]['process'].stdin.flush()
     return True
Exemplo n.º 6
0
    def send_broadcast(self, time, new_group=False):
        """ Broadcast a message to all hosts """
        if new_group:
            LOG.debug("Host:%i, Sending new_group:%f", self.host.id, time)
        else:
            LOG.debug("Host:%i, Sending present gid:%f", self.host.id, time)

        msg = struct.pack(self.msg_fmt, new_group, time, self.host.id)
        self.atomic_b.broadcast(msg)
Exemplo n.º 7
0
def remove_server(c, *args):
    """
    :c: cluster object
    :id: id of server to remove
    """
    # FIXME
    id = int(args[0])
    LOG.info("removing server %i", id)
    c.remove(id)
Exemplo n.º 8
0
    def __test_broadcast(self, args):
        config = None
        if args.file is not None:
            with open(args.file) as f:
                config = f.read()
                config = json.loads(config)
                LOG.debug("json loaded %s", config)

        # self.broadcaster.broadcast(' '.join(args.message).encode())
        # self.__configure_channels(self, args)
        self.broadcaster.test_broadcast(' '.join(args.message).encode(),
                                        config)
Exemplo n.º 9
0
def main():
    """main entry point"""
    command_handlers = {
        'server': run_server,
        'cluster': run_cluster,
    }

    parser = cli.configure_parser()
    args = parser.parse_args()

    LOG.setLevel(logging.DEBUG if args.verbose else logging.INFO)

    command_handlers[args.subcmd](args)
Exemplo n.º 10
0
    def __init__(self, args):
        self.port = 50000 + 100 * args.id
        self.servers = {}
        LOG.debug("starting server %i with port %i", args.id, self.port)
        LOG.debug("starting server with args %s", args)

        for server in args.servers:
            split = server.split(':')
            id = int(split[1])
            ip = split[0]
            self.servers[id] = Host(id, ip)
        self.servers[args.id] = Host(args.id, split[0])

        # LOG.debug("server list %s", self.servers)

        self.broadcaster = AtomicBroadcaster(args.id, self.port,
                                             self.servers, 1)

        # check if we running an membership protocol
        if args.protocol == 'periodic':
            self.periodic_group = PeriodicBroadcastGroup(self.broadcaster,
                                                         self.servers[args.id],
                                                         args.join)
        elif args.protocol == 'list':
            self.attendance = AttendanceListGroup(self.broadcaster,
                                                  self.servers[args.id],
                                                  args.join)
        elif args.protocol == 'neighbor':
            self.attendance = NeighborSurveillanceGroup(self.broadcaster,
                                                        self.servers[args.id],
                                                        args.join)

        self.commands = {
            'bc': self.__test_broadcast,
            'config': self.__configure_channels,
            'destroy': self.__destroy,
        }

        self.parser = cli.configure_parser()
        while True:
            cmd = input()
            LOG.info("cmd: %s", cmd)
            cmd = cmd.split()

            args = self.parser.parse_args(cmd)
            LOG.info(args)
            if args.subcmd not in self.commands:
                LOG.info("cmd not found")

            self.commands[args.subcmd](args)
Exemplo n.º 11
0
    def __membership_check(self, check_time):
        LOG.debug("host%i membership check task %f", self.host.id, check_time)
        # self.members.add(self.host.id)
        if self.host.id == max(self.members):
            self.send_list([self.host.id])
        gamma = len(self.members) * self.sigma
        confirm_time = check_time - time.time() + gamma
        confirm_task = th.Timer(confirm_time,
                                self.__membership_confirmation,
                                args=(check_time + gamma,))
        self.scheduled_tasks.append(confirm_task)
        confirm_task.start()

        mem_check_time = check_time - time.time() + self.period
        mem_check_task = th.Timer(mem_check_time,
                                  self.__membership_check,
                                  args=(check_time + self.period,))
        self.scheduled_tasks.append(mem_check_task)
        mem_check_task.start()
Exemplo n.º 12
0
    def __membership_confirmation(self, check_time):
        #TODO this is probably broken sends in delta check time instead of abs check time
        LOG.debug("host%i: membership confirm task", self.host.id)
        #time.time() > check_time:
        #    return
        if self.last_r_t + len(self.members) * self.sigma + .1 < check_time:
            LOG.debug("%i: SENDING NEW GROUP!!!!!!!!!!", self.host.id)
            new_group_time = time.time() + self.delta
            self.send_new_group(new_group_time)
            # self.send_broadcast(check_time + self.delta, new_group=True)
            self.present_members.add(self.host.id)

            confirm_time = new_group_time + 2 * self.delta
            confirm_task = th.Timer(confirm_time - time.time(),
                                    self.__new_group_confirmation,
                                    args=(new_group_time, ))
            # self.scheduled_broadcasts[confirm_time] = confirm_task
            self.scheduled_tasks.append(confirm_task)
            confirm_task.start()
Exemplo n.º 13
0
    def __new_group_confirmation(self, check_time):
        LOG.info("\033[95 m%i: members arrived before confirm %s\033[0m",
                 self.host.id, self.present_members)
        if self.present_members != self.members:
            LOG.debug("confirming: UPDATING mems from %s to %s",
                      self.members, self.present_members)
            self.members = self.present_members
            # self.group += self.period
            # self.group = check_time
            self.present_members = set([self.host.id])
            self.check_members = set([self.host.id])
        else:
            LOG.debug("%i: confirming: OKAY mems at %s", self.host.id,
                      self.members)
            self.check_members = set([self.host.id])
        # XXX
        # for key, task in self.scheduled_broadcasts.items():
            # # if msg[0] <= key:
            # task.cancel()
        # self.scheduled_broadcasts = {}

        for task in self.scheduled_tasks:
            task.cancel()
        self.scheduled_tasks = []
        # self.__membership_check(check_time)
        next_check_time = check_time + self.period
        next_check_task = th.Timer(next_check_time - time.time(),
                                   self.__membership_check,
                                   args=(next_check_time,))
        # self.scheduled_broadcasts[next_check_time] = next_check_task
        self.scheduled_tasks.append(next_check_task)
        next_check_task.start()
Exemplo n.º 14
0
    def __membership_confirmation_task(self, check_time):
        LOG.info("\033[95 m%i: members arrived before check %s\033[0m",
                 self.host.id, self.check_members)
        if self.check_members != self.cur_members:
            LOG.debug("confirming: UPDATING mems from %s to %s",
                      self.cur_members, self.check_members)
            self.cur_members = self.check_members
            self.cur_group += self.period
            # reset
            self.check_members = set([self.host.id])
        else:
            # XXX
            self.cur_group += self.period
            LOG.debug("%i: confirming: OKAY mems at %s", self.host.id,
                      self.cur_members)
            self.check_members = set([self.host.id])
        for key, task in self.scheduled_broadcasts.items():
            # if msg[0] <= key:
            task.cancel()
        self.scheduled_broadcasts = {}

        # schedule next check task; next check at check_time + period
        next_check_time = check_time + self.period
        next_check_task = th.Timer(next_check_time - time.time() - 1,
                                   self.__membership_check_task,
                                   args=(next_check_time, ))
        self.scheduled_broadcasts[next_check_time] = next_check_task
        next_check_task.start()
Exemplo n.º 15
0
    def add(self, id, ip='127.0.1.1', init=False, join=False):
        """
        adds server id to the cluster
        :id: new server's id
        """
        if id in self.servers:
            LOG.error("server %i already exists", id)
            return False
        elif id < 0 or id > 100:
            LOG.error("id %i is out of range [0, 100]", id)
            return False

        # TODO clean up
        args = ['python3', '-m', 'membership', 'server', '-s']
        # args += [ip + ':' + str(id) for id in self.servers]
        # if init:
        # args += [ip + ':' + str(id) for id in range(self.args.count)]
        args += [ip + ':' + str(i) for i in range(10)]

        if init and id == 0:
            args += ['-j']
        if join:
            args += ['-j']
        # else:
        # args += [ip + ':' + str(id) for id in self.servers]

        # LOG.debug("protocol: %s", self.args.protocol)
        if self.args.protocol == 'periodic':
            args += ['-p', self.args.protocol]
        elif self.args.protocol == 'neighbor':
            args += ['-p', self.args.protocol]
        elif self.args.protocol == 'list':
            args += ['-p', self.args.protocol]

        if self.args.verbose:
            args.append('-v')

        args += ['-i', str(id)]
        # open log file
        log = open(os.path.join('logs', str(id) + '.log'), 'w')
        LOG.info('starting server: %i', id)
        LOG.debug('arguments: %s', args)
        # spawn child process
        if self.args.debug:
            p = Popen(args, stdout=sys.stdout, stderr=sys.stderr, stdin=PIPE)
        else:
            p = Popen(args, stdout=log, stderr=log, stdin=PIPE)
        self.servers[id] = {'process': p, 'log': log}
        return True
Exemplo n.º 16
0
    def msg_handler(self, msg):
        """ Handle received message """
        msg_size = struct.unpack('i', msg.data[0:4])[0]
        #LOG.debug("size: %i, json: %s", msg_size, msg.data[4:4+msg_size])
        # LOG.debug("host%i recieved msg: %s", self.host.id, msg_dict)
        msg_dict = json.loads(msg.data[4:4 + msg_size].decode())

        # if "new-group" received
        if 'new_group' in msg_dict:
            # cancel membership_check and membership_confirmation tasks
            for task in self.scheduled_tasks:
                task.cancel()
            self.scheduled_tasks = []
            #can try if time.time > ['gid'] later
            LOG.info("%i: new_group %f, from %i", self.host.id,
                     msg_dict['gid'], msg_dict['id'])
            self.members = set()
            self.group = msg_dict['gid']
            self.send_present(msg_dict['gid'])
            LOG.debug("timer for %f",
                      msg_dict['gid'] - time.time() + self.period)
            self.present_members = set([self.host.id, msg_dict['id']])
            # confirm_time = new_group_time + 2 * self.delta
            wait_t = msg_dict['gid'] + 2 * self.delta - time.time()
            confirm_task = th.Timer(wait_t,
                                    self.__new_group_confirmation,
                                    args=(msg_dict['gid'], ))
            # self.scheduled_broadcasts[confirm_time] = confirm_task
            self.scheduled_tasks.append(confirm_task)
            confirm_task.start()

            # check_task = th.Timer(msg_dict['gid'] - time.time() + self.period,
            # self.__membership_check,
            # args=(msg_dict['gid'],))
            # check_task.start()
            # self.scheduled_tasks.append(check_task)

        elif 'present' in msg_dict:
            #TODO check correct group id
            LOG.info("%i: present %f, from %i", self.host.id, msg_dict['gid'],
                     msg_dict['id'])
            # self.members.add(msg_dict['id'])
            self.present_members.add(msg_dict['id'])

        elif 'list' in msg_dict:
            #TODO check time < O and gamma
            LOG.info("%i: list received", self.host.id)
            self.last_r_t = time.time(
            )  #TODO this is O not 0 needs to be fixed
Exemplo n.º 17
0
    def __forward_task(self, msg):
        """ determine the channels to forward msg on """
        duration = msg.get_timely_deadline(self.sigma) - time.time()
        # LOG.debug('sleeping for %f in task', duration)
        time.sleep(duration)

        self.c_hist_lock.acquire()

        highest_chan_recv = self.c_history[(msg.time, msg.host)]['c']  # c
        highest_chan_send = self.channel_count - msg.hops  # f + 1 - h

        # check if c < f + 1 - h
        if highest_chan_recv < highest_chan_send:
            LOG.info("%i is forwarding msg from %i", self.server_port,
                     msg.host)
            msg.add_hop()
            # forward on channels c + 1, ..., f + 1 - h
            for channel in self.channels[highest_chan_recv:highest_chan_send]:
                for _, host in self.hosts.items():
                    if host.id == self.server_id:
                        continue
                    channel.send(host.ip, host.port, msg)

        self.c_hist_lock.release()
Exemplo n.º 18
0
 def send_list(self, members):
     LOG.debug("host%i sending list %s", self.host.id, members)
     msg_dict = {'list': True, 'gid': self.group, 'members': list(members)}
     msg_bytes = json.dumps(msg_dict).encode()
     msg_size = struct.pack('i', len(msg_bytes))
     dest = self.get_next_host()
     if self.host.id == max(self.members):
         dest = min(self.members)
     msg = Message(None, msg_size + msg_bytes, -1)
     msg.hops = -1
     msg.time = 0
     msg.host = -1
     msg.chan = -1
     LOG.debug("host%i, sending list to host%i", self.host.id, dest)
     LOG.debug("members: %s", self.members)
     port = 50000 + (100 * dest) + 1
     # send on the first channel, abuse the system
     self.atomic_b.channels[0].socket.sendto(
         msg.marshal(), (socket.gethostbyname(socket.gethostname()), port))
Exemplo n.º 19
0
    def remove(self, id):
        """
        removes server id from the cluster
        :id: server id to remove
        """
        if id not in self.servers:
            LOG.error("server %i does not exists", id)
            return False
        buf = 'destroy'
        LOG.debug("sending %s to server %i", buf, id)
        buf += '\n'
        self.servers[id]['process'].stdin.write(buf.encode())
        self.servers[id]['process'].stdin.flush()

        time.sleep(1)

        LOG.info("forcibly terminating server %i", id)
        self.servers[id]['log'].close()
        self.servers[id]['process'].kill()
        del self.servers[id]
Exemplo n.º 20
0
    def msg_handler(self, msg):
        """ Handle receipt of broadcasts """
        msg = struct.unpack(self.msg_fmt, msg.data[:20])
        # if on time; myclock > V abort
        # if msg[1] < time.time():
        # if msg[1] > (time.time() - .2):
        if True:
            # LOG.debug("TIME, MYCLOCK: %s, %s", msg[1], time.time() - .2)
            # if "new-group" received
            if msg[0]:
                # cancel broadcasts
                # LOG.debug("new group %s", self.scheduled_broadcasts)
                for key, task in self.scheduled_broadcasts.items():
                    # if msg[0] <= key:
                    task.cancel()
                self.scheduled_broadcasts = {}

                LOG.info("%i: new group requested", self.host.id)
                self.cur_group = msg[1]
                self.cur_period = 0
                self.check_members = set([self.host.id, msg[2]])
                self.send_broadcast(msg[1])

                # schedule check for the new group req
                confirm_task = th.Timer(2 * self.delta,
                                        self.__membership_confirmation_task,
                                        args=(msg[1], ))

                confirm_task.start()

            # if "present" received
            else:
                LOG.info("%i: member added %d", self.host.id, msg[2])
                # put the member in the group
                # if self.cur_group == msg[1]:
                self.check_members.add(msg[2])
                # LOG.info("%i: members after add %s", self.host.id,
                # self.check_members)
        else:
            LOG.info("LATE %s, %s", msg[1], time.time())
Exemplo n.º 21
0
 def destroy(self):
     for chan in self.channels:
         chan.destroy()
     LOG.info("destroying broadcaster")