class Munager_test:
    def __init__(self, config):
        self.config = config

        # set logger
        self.logger = logging.getLogger()

        # mix
        self.ioloop = IOLoop.current()
        self.mu_api = MuAPI(self.config)
        print(self.mu_api.get_node_info())
        self.logger.info('Munager initializing.')

    @gen.coroutine
    def upload_serverload(self):
        # update online users count
        try:
            uptime = self._uptime()
            load = self._load()
            result = yield self.mu_api.upload_systemload(uptime, load)
            if result:
                self.logger.info(
                    'upload_system load success. uptime {}, load {}'.format(
                        uptime, load))
        except HTTPError:
            self.logger.warning('upload_system load failed')

    @staticmethod
    def _second_to_msecond(period):
        # s to ms
        return period * 1000

    @staticmethod
    def _uptime():
        with open('/proc/uptime', 'r') as f:
            return float(f.readline().split()[0])

    @staticmethod
    def _load():
        import os
        return os.popen("cat /proc/loadavg | awk '{ print $1\" \"$2\" \"$3 }'"
                        ).readlines()[0]

    def run(self):
        # period task

        PeriodicCallback(
            callback=self.upload_serverload,
            callback_time=self._second_to_msecond(
                self.config.get("upload_serverload_period", 60)),
            io_loop=self.ioloop,
        ).start()

        try:
            # Init task
            self.ioloop.run_sync(self.upload_serverload)
            self.ioloop.start()
        except KeyboardInterrupt:
            del self.mu_api
            print('Bye~')
    def __init__(self, config):
        self.config = config

        # set logger
        self.logger = logging.getLogger()

        # mix
        self.ioloop = IOLoop.current()
        self.mu_api = MuAPI(self.config)
        print(self.mu_api.get_node_info())
        self.logger.info('Munager initializing.')
Example #3
0
    def __init__(self, config):
        self.config = config

        # set logger
        self.logger = logging.getLogger()
        self.alive_count = 0

        # mix
        self.ioloop = IOLoop.current()
        self.mu_api = MuAPI(self.config)
        self.ss_manager = SSManager(self.config)
        self.logger.info('Munager initializing.')
Example #4
0
    def __init__(self):
        self.config = load_config()

        # set logger
        self.logger = logging.getLogger()
        # mix
        self.mu_api = MuAPI()

        self.manager = V2Manager()

        self.first_time_start = True
        self.event = threading.Event()
        self.has_stopped = False
    def __init__(self, config):
        self.config = config

        # set logger
        self.logger = logging.getLogger()

        # mix
        self.ioloop = IOLoop.current()
        self.mu_api = MuAPI(self.config)
        node_info = self.mu_api.get_node_info()
        self.logger.info("Node infos: {}".format(node_info))

        self.manager = V2Manager(self.config, next_node_info=node_info)

        self.first_time_start = True
    def __init__(self, config):
        self.config = config

        # set logger
        self.logger = logging.getLogger()

        # mix
        self.ioloop = IOLoop.current()
        self.mu_api = MuAPI(self.config)
        self.node_info = self.mu_api.get_node_info()
        self.logger.info("Node infos: {}".format(self.node_info))
        if self.node_info['sort'] == 0:
            self.ss_manager = SSManager(self.config)
        elif self.node_info['sort'] == 11:
            self.v2_manager = V2Manager(self.config)
        self.logger.info('Munager initializing.')
class Munager:
    def __init__(self, config):
        self.config = config

        # set logger
        self.logger = logging.getLogger()

        # mix
        self.ioloop = IOLoop.current()
        self.mu_api = MuAPI(self.config)
        self.node_info = self.mu_api.get_node_info()
        self.logger.info("Node infos: {}".format(self.node_info))
        if self.node_info['sort'] == 0:
            self.ss_manager = SSManager(self.config)
        elif self.node_info['sort'] == 11:
            self.v2_manager = V2Manager(self.config)
        self.logger.info('Munager initializing.')

    @gen.coroutine
    def upload_serverload(self):
        # update online users count
        try:
            uptime = self._uptime()
            load = self._load()
            result = yield self.mu_api.upload_systemload(uptime, load)
            if result:
                self.logger.info(
                    'upload_system load success. uptime {}, load {}'.format(
                        uptime, load))
        except HTTPError:
            self.logger.warning('upload_system load failed')

    @gen.coroutine
    def upload_speedtest(self):
        # update online users count
        try:
            speedtest_result = speedtest_thread()
            result = yield self.mu_api.upload_speedtest(speedtest_result)
            if result:
                self.logger.info(
                    'Successfully upload speet test result {}.'.format(
                        speedtest_result))
        except HTTPError:
            self.logger.warning('failed to upload online user count.')

    @gen.coroutine
    def update_ss_manager(self):
        # get from MuAPI and ss-manager
        users = yield self.mu_api.get_users('port')
        state = self.ss_manager.state
        self.logger.info(
            'get MuAPI and ss-manager succeed, now begin to check ports.')
        #self.logger.debug('get state from ss-manager: {}.'.format(state))

        # remove port
        for port in state:
            if port not in users or not users.get(port).available:
                self.ss_manager.remove(port)
                self.logger.info('remove port: {}.'.format(port))

        # add port
        for port, user in users.items():
            user_id = user.id
            if user.available and port not in state:
                if self.ss_manager.add(
                        user_id=user_id,
                        port=user.port,
                        password=user.passwd,
                        method=user.method,
                        plugin=user.plugin,
                        plugin_opts=user.plugin_opts,
                ):
                    self.logger.info('add user at port: {}.'.format(user.port))

            if user.available and port in state:
                if user.passwd != state.get(port).get('password') or \
                                user.method != state.get(port).get('method') or \
                                user.plugin != state.get(port).get('plugin') or \
                                user.plugin_opts != state.get(port).get('plugin_opts'):
                    if self.ss_manager.remove(
                            user.port) and self.ss_manager.add(
                                user_id=user_id,
                                port=user.port,
                                password=user.passwd,
                                method=user.method,
                                plugin=user.plugin,
                                plugin_opts=user.plugin_opts,
                            ):
                        self.logger.info(
                            'reset port {} due to method or password changed.'.
                            format(user.port))
        # check finish
        self.logger.info('check ports finished.')

    @gen.coroutine
    def upload_ss_throughput(self):
        state = self.ss_manager.state
        online_amount = 0
        for port, info in state.items():
            cursor = info.get('cursor')
            throughput = info.get('throughput')
            if throughput < cursor:
                online_amount += 1
                self.logger.warning('error throughput, try fix.')
                self.ss_manager.set_cursor(port, throughput)
            elif throughput > cursor:
                online_amount += 1
                dif = throughput - cursor
                user_id = info.get('user_id')
                try:
                    result = yield self.mu_api.upload_throughput(user_id, dif)
                    if result:
                        self.ss_manager.set_cursor(port, throughput)
                        self.logger.info(
                            'update traffic: {} for port: {}.'.format(
                                dif, port))
                except:
                    self.logger.info('update trafic faileds')

        # update online users count
        try:
            result = yield self.mu_api.post_online_user(online_amount)
            if result:
                self.logger.info(
                    'upload online user count: {}.'.format(online_amount))
        except HTTPError:
            self.logger.warning('failed to upload online user count.')

    @staticmethod
    def _second_to_msecond(period):
        # s to ms
        return period * 1000

    @staticmethod
    def _uptime():
        with open('/proc/uptime', 'r') as f:
            return float(f.readline().split()[0])

    @staticmethod
    def _load():
        import os
        return os.popen("cat /proc/loadavg | awk '{ print $1\" \"$2\" \"$3 }'"
                        ).readlines()[0]

    def run(self):
        # period task
        if self.node_info['sort'] == 0:
            PeriodicCallback(
                callback=self.update_ss_manager,
                callback_time=self._second_to_msecond(
                    self.config.get('update_port_period', 60)),
                io_loop=self.ioloop,
            ).start()
            PeriodicCallback(
                callback=self.upload_ss_throughput,
                callback_time=self._second_to_msecond(
                    self.config.get('upload_throughput_period', 360)),
                io_loop=self.ioloop,
            ).start()
        PeriodicCallback(
            callback=self.upload_serverload,
            callback_time=self._second_to_msecond(
                self.config.get("upload_serverload_period", 60)),
            io_loop=self.ioloop,
        ).start()
        PeriodicCallback(callback_time=self._second_to_msecond(
            self.config.get("upload_speedtest_period", 21600)),
                         callback=self.upload_speedtest,
                         io_loop=self.ioloop).start()
        try:
            # Init task
            self.ioloop.run_sync(self.upload_serverload)
            self.ioloop.start()
        except KeyboardInterrupt:
            del self.mu_api
            if self.node_info['sort'] == 0:
                del self.ss_manager
            elif self.node_info['sort'] == 11:
                del self.v2_manager
            print('Bye~')
class Munager:
    def __init__(self, config):
        self.config = config

        # set logger
        self.logger = logging.getLogger()

        # mix
        self.ioloop = IOLoop.current()
        self.mu_api = MuAPI(self.config)
        node_info = self.mu_api.get_node_info()
        self.logger.info("Node infos: {}".format(node_info))

        self.manager = V2Manager(self.config, next_node_info=node_info)

        self.first_time_start = True

    @gen.coroutine
    def upload_serverload(self):
        # update online users count
        try:
            uptime = self._uptime()
            load = self._load()
            result = yield self.mu_api.upload_systemload(uptime, load)
            if result:
                self.logger.info(
                    'upload_system load success. uptime {}, load {}'.format(
                        uptime, load))
        except HTTPError:
            self.logger.warning('upload_system load failed')

    @gen.coroutine
    def upload_speedtest(self):
        # update online users count
        try:
            speedtest_result = speedtest_thread()
            result = yield self.mu_api.upload_speedtest(speedtest_result)
            if result:
                self.logger.info(
                    'Successfully upload speet test result {}.'.format(
                        speedtest_result))
        except HTTPError:
            self.logger.warning('failed to upload online user count.')

    @gen.coroutine
    def update_manager(self):
        new_node_info = self.mu_api.get_node_info()
        self.logger.info("Old Node infos: {}".format(
            self.manager.next_node_info))
        self.logger.info("New Node infos: {}".format(new_node_info))
        if json.dumps(self.manager.next_node_info,sort_keys=True,indent=2) != json.dumps(new_node_info,sort_keys=True,indent=2)\
                or self.first_time_start:
            self.manager.next_node_info = new_node_info
            self.manager.update_server()
            self.first_time_start = False
        # get from MuAPI and ss-manager
        users = yield self.mu_api.get_users('email',
                                            self.manager.next_node_info)
        current_user = self.manager.get_users()
        self.logger.info(
            'get MuAPI and ss-manager succeed, now begin to check ports.')
        # self.logger.debug('get state from ss-manager: {}.'.format(state))

        # remove user by prefixed_id
        for prefixed_id in current_user:
            if prefixed_id not in users or not users.get(
                    prefixed_id).available:
                self.manager.remove(prefixed_id)
                self.logger.info(
                    'need to remove client: {}.'.format(prefixed_id))

        # add prefixed_id
        for prefixed_id, user in users.items():
            if user.available and prefixed_id not in current_user:
                if self.manager.add(user):
                    self.logger.info(
                        'need to add user email {}.'.format(prefixed_id))

            if user.available and prefixed_id in current_user:
                if user != current_user.get(prefixed_id):
                    if self.manager.remove(prefixed_id) and self.manager.add(
                            user):
                        self.logger.info(
                            'need to reset user {} due to method or password changed.'
                            .format(prefixed_id))

        # check finish
        self.logger.info('check ports finished.')
        self.logger.info("if update {}".format(self.manager.if_user_change))
        if self.manager.if_user_change:
            self.manager.if_user_change = False
            self.manager.update_users()
            self.manager.current_node_info = self.manager.next_node_info

    @gen.coroutine
    def upload_throughput(self):
        current_user = self.manager.get_users()
        online_amount = 0
        for prefixed, user in current_user.items():
            laset_traffic_upload, laset_traffic_download, user_id = self.manager.get_last_traffic(
                user)
            current_upload,current_download = self.manager.client.get_user_traffic_uplink(user.email),\
                                            self.manager.client.get_user_traffic_downlink(user.email)
            if current_download is None:
                current_download = 0
            else:
                current_download = int(current_download)
            if current_upload is None:
                current_upload = 0
            else:
                current_upload = int(current_upload)

            if current_download + current_upload < laset_traffic_upload + laset_traffic_download:
                online_amount += 1
                self.logger.warning('error throughput, try fix.')
                self.manager.set_current_traffic(user,
                                                 upload=current_upload,
                                                 download=current_download)
            elif current_download + current_upload > laset_traffic_upload + laset_traffic_download:
                online_amount += 1
                upload_dif = current_upload - laset_traffic_upload
                download_dif = current_download - laset_traffic_download
                try:
                    result = yield self.mu_api.upload_throughput(
                        user_id, upload=upload_dif, donwload=download_dif)
                    if result:
                        self.manager.set_current_traffic(
                            user=user,
                            upload=current_upload,
                            download=current_download)
                        self.logger.info(
                            'update traffic: Upload {}, Download {} for user: {}.'
                            .format(upload_dif, download_dif,
                                    user.prefixed_id))
                except:
                    self.logger.info('update trafic faileds')

        # update online users count
        try:
            result = yield self.mu_api.post_online_user(online_amount)
            if result:
                self.logger.info(
                    'upload online user count: {}.'.format(online_amount))
        except HTTPError:
            self.logger.warning('failed to upload online user count.')

    @staticmethod
    def _second_to_msecond(period):
        # s to ms
        return period * 1000

    @staticmethod
    def _uptime():
        with open('/proc/uptime', 'r') as f:
            return float(f.readline().split()[0])

    @staticmethod
    def _load():
        import os
        return os.popen("cat /proc/loadavg | awk '{ print $1\" \"$2\" \"$3 }'"
                        ).readlines()[0]

    def run(self):
        # period task
        PeriodicCallback(
            callback=self.update_manager,
            callback_time=self._second_to_msecond(
                self.config.get('update_port_period', 60)),
        ).start()
        PeriodicCallback(
            callback=self.upload_throughput,
            callback_time=self._second_to_msecond(
                self.config.get('upload_throughput_period', 360)),
        ).start()
        # PeriodicCallback(
        #     callback=self.upload_serverload,
        #     callback_time=self._second_to_msecond(self.config.get("upload_serverload_period", 60)),
        # ).start()
        if self.config.get("speedtest", False):
            PeriodicCallback(
                callback_time=self._second_to_msecond(
                    self.config.get("upload_speedtest_period", 21600)),
                callback=self.upload_speedtest,
            ).start()
        try:
            # Init task
            self.ioloop.run_sync(self.update_manager)
            self.ioloop.start()
        except KeyboardInterrupt:
            del self.mu_api
            del self.manager
            print('Bye~')
Example #9
0
class Munager:
    def __init__(self, config):
        self.config = config

        # set logger
        self.logger = logging.getLogger()

        # mix
        self.ioloop = IOLoop.current()
        self.mu_api = MuAPI(self.config)
        self.ss_manager = SSManager(self.config)
        self.logger.info('Munager initializing.')

        self.client = AsyncHTTPClient()

    @gen.coroutine
    def update_ss_manager(self):
        # get from MuAPI and ss-manager
        users = yield self.mu_api.get_users('port')
        state = self.ss_manager.state
        self.logger.info('get MuAPI and ss-manager succeed, now begin to check ports.')
        self.logger.debug('get state from ss-manager: {}.'.format(state))

        # remove port
        for port in state:
            if port not in users or not users.get(port).available:
                self.ss_manager.remove(port)
                self.logger.info('remove port: {}.'.format(port))

        # add port
        for port, user in users.items():
            user_id = user.id
            if user.available and port not in state:
                if self.ss_manager.add(
                        user_id=user_id,
                        port=user.port,
                        password=user.passwd,
                        method=user.method,
                        plugin=user.plugin,
                        plugin_opts=user.plugin_opts,
                ):
                    self.logger.info('add user at port: {}.'.format(user.port))

            if user.available and port in state:
                if user.passwd != state.get(port).get('password') or \
                                user.method != state.get(port).get('method') or \
                                user.plugin != state.get(port).get('plugin') or \
                                user.plugin_opts != state.get(port).get('plugin_opts'):
                    if self.ss_manager.remove(user.port) and self.ss_manager.add(
                            user_id=user_id,
                            port=user.port,
                            password=user.passwd,
                            method=user.method,
                            plugin=user.plugin,
                            plugin_opts=user.plugin_opts,
                    ):
                        self.logger.info('reset port {} due to method or password changed.'.format(user.port))
        # check finish
        self.logger.info('check ports finished.')

    @gen.coroutine
    def upload_throughput(self):
        state = self.ss_manager.state
        online_amount = 0
        for port, info in state.items():
            cursor = info.get('cursor')
            throughput = info.get('throughput')
            if throughput < cursor:
                online_amount += 1
                self.logger.warning('error throughput, try fix.')
                self.ss_manager.set_cursor(port, throughput)
            elif throughput > cursor:
                online_amount += 1
                dif = throughput - cursor
                user_id = info.get('user_id')
                try:
                    result = yield self.mu_api.upload_throughput(user_id, dif)
                    if result:
                        self.ss_manager.set_cursor(port, throughput)
                        self.logger.info('update traffic: {} for port: {}.'.format(dif, port))


        # update online users count
        try:
            result = yield self.mu_api.post_online_user(online_amount)
            if result:
                self.logger.info('upload online user count: {}.'.format(online_amount))
        except HTTPError:
            self.logger.warning('failed to upload online user count.')

    @staticmethod
    def _second_to_msecond(period):
        # s to ms
        return period * 1000

    def run(self):
        # period task
        PeriodicCallback(
            callback=self.update_ss_manager,
            callback_time=self._second_to_msecond(self.config.get('update_port_period', 60)),
            io_loop=self.ioloop,
        ).start()
        PeriodicCallback(
            callback=self.upload_throughput,
            callback_time=self._second_to_msecond(self.config.get('upload_throughput_period', 360)),
            io_loop=self.ioloop,
        ).start()
        try:
            # Init task
            self.ioloop.run_sync(self.update_ss_manager)
            self.ioloop.start()
        except KeyboardInterrupt:
            del self.mu_api
            del self.ss_manager
            print('Bye~')
Example #10
0
class Munager(object):
    def __init__(self):
        self.config = load_config()

        # set logger
        self.logger = logging.getLogger()
        # mix
        self.mu_api = MuAPI()

        self.manager = V2Manager()

        self.first_time_start = True
        self.event = threading.Event()
        self.has_stopped = False

    def update_manager(self):

        new_node_info = self.mu_api.get_node_info()
        if new_node_info:
            self.logger.info("Old Node infos: {}".format(
                self.manager.next_node_info))
            self.logger.info("New Node infos: {}".format(new_node_info))
            if json.dumps(self.manager.next_node_info,
                          sort_keys=True,
                          indent=2) != json.dumps(
                              new_node_info, sort_keys=True, indent=2):
                self.manager.next_node_info = new_node_info
                self.manager.update_server()
                self.manager.if_user_change = True
            # get from MuAPI and ss-manager
            users = self.mu_api.get_users('email', self.manager.next_node_info)
            current_user = self.manager.get_users()
            self.logger.info(
                'get MuAPI and ss-manager succeed, now begin to check ports.')

            # remove user by prefixed_id
            for prefixed_id in current_user:
                if prefixed_id not in users or not users.get(
                        prefixed_id).available:
                    self.manager.remove(prefixed_id)
                    self.logger.info(
                        'need to remove client: {}.'.format(prefixed_id))

            # add prefixed_id
            for prefixed_id, user in users.items():
                if user.available and prefixed_id not in current_user:
                    if self.manager.add(user):
                        self.logger.info(
                            'need to add user email {}.'.format(prefixed_id))

                if user.available and prefixed_id in current_user:
                    if user != current_user.get(prefixed_id):
                        if self.manager.remove(
                                prefixed_id) and self.manager.add(user):
                            self.logger.info(
                                'need to reset user {} due to method or password changed.'
                                .format(prefixed_id))

            # check finish
            self.logger.info('check ports finished.')
            self.logger.info("if update {}".format(
                self.manager.if_user_change))
            if self.manager.if_user_change:
                self.manager.if_user_change = False
                self.manager.update_users()
                self.manager.current_node_info = self.manager.next_node_info
        else:
            # self.manager.next_node_info or new_node_info 此时 current不为空
            # 选择直接初始化全部用户
            # start remove inbounds
            self.logger.info("initial system")
            self.manager.remove_inbounds()
            self.manager.users_to_be_removed = deepcopy(self.manager.users)
            self.manager.users_to_be_add = {}
            self.manager.update_users()
            self.manager.current_node_info = None
            self.manager.next_node_info = None
            self.first_time_start = True

    def upload_throughput(self):
        current_user = self.manager.get_users()
        data = []
        ips = []
        for prefixed, user in current_user.items():
            current_upload,current_download = self.manager.client.get_user_traffic_uplink(user.email),\
                                            self.manager.client.get_user_traffic_downlink(user.email)
            if current_download is None:
                current_download = 0
            else:
                current_download = int(current_download)
            if current_upload is None:
                current_upload = 0
            else:
                current_upload = int(current_upload)

            if current_download + current_upload > 0:
                upload_dif = current_upload
                download_dif = current_download
                data.append({
                    'u': upload_dif,
                    'd': download_dif,
                    'user_id': user.user_id
                })
                if current_download + current_upload > 1024:
                    user_ips = self.manager.client.get_user_aliveips(
                        user.email)
                    if user_ips:
                        for ip in user_ips:
                            ips.append({'ip': ip, 'user_id': user.user_id})
        if self.mu_api.upload_throughput(data):
            self.logger.info("Successfully upload {} users traffics".format(
                len(data)))
            del data
        else:
            self.logger.info('update trafic failed')
        if self.mu_api.upload_online_ips(ips):
            self.logger.info("Successfully upload {} ips".format(len(ips)))
            del ips
        else:
            self.logger.info('update online ips failed')

        self.mu_api.upload_systemload()

    @staticmethod
    def del_servers():
        global db_instance
        db_instance.logger.info("Shut Down")
        db_instance.manager.remove_inbounds()
        db_instance.manager.users_to_be_removed = deepcopy(
            db_instance.manager.users)
        db_instance.manager.users_to_be_add = {}
        db_instance.manager.update_users()
        db_instance.manager.current_node_info = None
        db_instance.manager.next_node_info = None
        db_instance.first_time_start = True

    @staticmethod
    def thread_db(obj):
        global db_instance
        timeout = 60
        socket.setdefaulttimeout(timeout)
        db_instance = obj()
        try:
            import resource
            logging.info(
                'current process RLIMIT_NOFILE resource: soft %d hard %d' %
                resource.getrlimit(resource.RLIMIT_NOFILE))
        except:
            pass
        try:
            while True:
                try:
                    ping = db_instance.mu_api.webapi.getApi('func/ping')
                    if ping is None:
                        logging.error(
                            'something wrong with your http api, please check your config and website status and try again later.'
                        )
                    else:
                        db_instance.update_manager()
                        db_instance.upload_throughput()
                except Exception as e:
                    trace = traceback.format_exc()
                    logging.error(trace)
                    # logging.warn('db thread except:%s' % e)
                if db_instance.event.wait(timeout):
                    break
                if db_instance.has_stopped:
                    break
        except KeyboardInterrupt as e:
            pass
        db_instance.del_servers()
        db_instance = None

    @staticmethod
    def thread_db_stop():
        global db_instance
        db_instance.has_stopped = True
        db_instance.event.set()