Beispiel #1
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()
Beispiel #2
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()
Beispiel #3
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)
Beispiel #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)
Beispiel #5
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)
Beispiel #6
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
Beispiel #7
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)
Beispiel #8
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)
Beispiel #9
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
Beispiel #10
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
Beispiel #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()
Beispiel #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()
Beispiel #13
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]
Beispiel #14
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))