def update_poolrate(pool_list, run_time, db, retry):
    pool_queue = queue.Queue()
    hashrate_queue = queue.Queue()

    for p in pool_list:
        if p['name'] in ['ghash', 'ozcoin', 'btcchina', 'kano', 'cksolo']:
            pool_queue.put(p)

    for i in range(len(pool_list)):
        pool_thread = PoolThread(pool_queue, hashrate_queue, retry)
        pool_thread.daemon = True
        pool_thread.start()
    pool_queue.join()

    column = ['time']
    value = [run_time]
    while not hashrate_queue.empty():
        h = hashrate_queue.get(False)
        column.append(h['name'])
        value.append(h['hashrate'])

    database = DataBase(db)
    database.connect()

    if not database.run('insert', 'hashrate', column, value):
        for i in range(len(column) - 1):
            database.run(
                'raw',
                'ALTER TABLE hashrate ADD `{}` DOUBLE'.format(column[i + 1])
            )
        database.commit()
        database.run('insert', 'hashrate', column, value)

    database.commit()
    database.disconnect()
def luciThread(node_queue, result_queue, commands, db, log, lock):
    database = DataBase(db)
    database.connect()
    while True:
        try:
            node = node_queue.get(False)
        except:
            break

        database.start_transaction()
        result = database.run('select', 'controller_security', ['password'],
                              "`ip` = %s FOR UPDATE", [node['ip']])
        if not result or not result[0]:
            password = ''
        else:
            password = result[0][0] if result[0][0] is not None else ''

        error = False
        auth = True
        for i in range(3):
            j = 0
            try:
                luci = ams.luci.LuCI(node['ip'], 80, password)
                if not luci.auth():
                    luci = ams.luci.LuCI(node['ip'], 80, '')
                if not luci.auth():
                    auth = False
                    error = True
                    break
                auth = True
                database.commit()
                result = []
                for c in commands[j:]:
                    if c['params'] is not None:
                        for i, param in enumerate(c['params']):
                            c['params'][i] = param.replace(
                                '`ip4`', node['ip'].split('.')[3])
                    if c['method'] == 'user.setpasswd':
                        new_password = base64.b64encode(os.urandom(9)).decode()
                        c['params'] = ['root', new_password]
                        database.start_transaction()
                        result = database.run('select', 'controller_security',
                                              ['password'],
                                              "`ip` = %s FOR UPDATE",
                                              [node['ip']])

                    r = luci.put(c['lib'], c['method'], c['params'], i + 10)

                    if c['method'] == 'user.setpasswd':
                        if r['error'] is None:
                            database.run(
                                'raw', '''\
INSERT INTO controller_security
       (ip, password)
VALUES (%s, %s)
    ON DUPLICATE KEY UPDATE
       password = %s''', [node['ip'], new_password, new_password])
                        database.commit()

                    with lock:
                        log.debug('[{}][{}][{}][{}][{}]'.format(
                            node['ip'],
                            c['method'],
                            '|'.join(c['params']),
                            r['result'],
                            r['error'],
                        ))

                    result.append(r)

                    j += 1
                error = False
                break
            except Exception as e:
                with lock:
                    log.error('[{}]'.format(e))
                error = True
                continue

        if not auth:
            result.append({'result': 'Authentication Failed'})
        elif error:
            result.append({'result': 'Connection Failed'})
        result_queue.put({
            'node': node,
            'result': result,
            'error': error,
        })
        node_queue.task_done()
    database.disconnect()

cfgfile = os.path.join(os.environ.get('VIRTUAL_ENV') or '/', 'etc/ams.conf')


def readCfg(filename):
    import configparser
    config = configparser.ConfigParser(interpolation=None)
    config.read(filename, encoding="utf8")
    return config


if __name__ == '__main__':
    cfg = readCfg(cfgfile)
    db = cfg['DataBase']
    database = DataBase(db)
    database.connect()

    database.run(
        command='create',
        name='blocks',
        column_def=[
            {'name': 'time', 'type': 'TIMESTAMP DEFAULT "0000-00-00 00:00:00"'},
            {'name': 'ip', 'type': 'VARCHAR(40)'},
            {'name': 'port', 'type': 'SMALLINT UNSIGNED'},
            {'name': 'blocks', 'type': 'INT UNSIGNED'}
        ],
        additional='PRIMARY KEY (`time`, `ip`, `port`)',
    )
    minerList = database.run('select', 'controller_config', ['ip', 'port'])

cfgfile = os.path.join(os.environ.get('VIRTUAL_ENV') or '/', 'etc/ams.conf')


def readCfg(filename):
    import configparser
    config = configparser.ConfigParser(interpolation=None)
    config.read(filename, encoding="utf8")
    return config


if __name__ == '__main__':
    cfg = readCfg(cfgfile)
    db = cfg['DataBase']
    database = DataBase(db)
    database.connect()

    columns = []

    for i in range(4):
        for j in range(18, 22):
            columns.append({
                'name': 'mw{}_{}'.format(i, j),
                'type': 'INT',
            })
            for name in ['ghsmm0', 'eratio']:
                columns.append({
                    'name': '{}{}_{}'.format(name, i, j),
                    'type': 'DOUBLE',
                })
def update_poolrate(pool_list, run_time, db, retry):
    pool_queue = queue.Queue()
    hashrate_queue = queue.Queue()

    for p in pool_list:
        if p['name'] in ['ghash', 'ozcoin', 'btcchina', 'kano', 'cksolo']:
            pool_queue.put(p)

    for i in range(len(pool_list)):
        pool_thread = PoolThread(pool_queue, hashrate_queue, retry)
        pool_thread.daemon = True
        pool_thread.start()
    pool_queue.join()

    column = ['time']
    value = [run_time]
    while not hashrate_queue.empty():
        h = hashrate_queue.get(False)
        column.append(h['name'])
        value.append(h['hashrate'])

    database = DataBase(db)
    database.connect()

    if not database.run('insert', 'hashrate', column, value):
        for i in range(len(column) - 1):
            database.run(
                'raw',
                'ALTER TABLE hashrate ADD `{}` DOUBLE'.format(column[i + 1]))
        database.commit()
        database.run('insert', 'hashrate', column, value)

    database.commit()
    database.disconnect()
Beispiel #6
0
def update(argv):
    import datetime
    from multiprocessing import Process

    from ams.farm import Farm
    from ams.pool import update_poolrate
    from ams.sql import sql_handler, DataBase, SQLQueue

    cfg = readCfg(cfgfile)
    db = cfg['DataBase']
    farm_type = cfg['Farm']['type']

    database = DataBase(db)
    database.connect()
    controllerList = database.run(
        'select', 'controller_config', ['ip', 'port', 'mods'])
    if not controllerList:
        print("No miner found.\n Run subcommand 'controller' to add.")
        exit()

    miners = [
        {
            'ip': m[0],
            'port': m[1],
            # 'mods': [int(mod) for mod in m[2].split(',')]
            'mods': m[2],
        }
        for m in controllerList
    ]
    myFarm = Farm(miners, farm_type)

    poolList = database.run(
        'select', 'pool_config',
        ['name', 'user', 'worker', 'key', 'seckey']
    )
    # TODO: should automatically get worker name from cgminer api
    if not poolList:
        pools = []
    else:
        pools = [
            {
                'name': p[0],
                'user': p[1],
                'worker': p[2],
                'key': p[3],
                'seckey': p[4]
            } for p in poolList
        ]
    database.disconnect()

    now = '{:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())
    sql_queue = SQLQueue()

    farm_process = Process(
        target=myFarm.run,
        args=(now, sql_queue, 5, 100)
    )
    pool_process = Process(
        target=update_poolrate,
        args=(pools, now, db, 3)
    )
    db_process = Process(
        target=sql_handler,
        args=(sql_queue, db, int(db['thread_num']))
    )
    db_process.start()
    pool_process.start()
    farm_process.start()
    pool_process.join()
    farm_process.join()
    db_process.join()
def luciThread(node_queue, result_queue, commands, db, log, lock):
    database = DataBase(db)
    database.connect()
    while True:
        try:
            node = node_queue.get(False)
        except:
            break

        database.start_transaction()
        result = database.run(
            'select',
            'controller_security',
            ['password'],
            "`ip` = %s FOR UPDATE",
            [node['ip']]
        )
        if not result or not result[0]:
            password = ''
        else:
            password = result[0][0] if result[0][0] is not None else ''

        error = False
        auth = True
        for i in range(3):
            j = 0
            try:
                luci = ams.luci.LuCI(node['ip'], 80, password)
                if not luci.auth():
                    luci = ams.luci.LuCI(node['ip'], 80, '')
                if not luci.auth():
                    auth = False
                    error = True
                    break
                auth = True
                database.commit()
                result = []
                for c in commands[j:]:
                    if c['params'] is not None:
                        for i, param in enumerate(c['params']):
                            c['params'][i] = param.replace(
                                '`ip4`', node['ip'].split('.')[3]
                            )
                    if c['method'] == 'user.setpasswd':
                        new_password = base64.b64encode(os.urandom(9)).decode()
                        c['params'] = ['root', new_password]
                        database.start_transaction()
                        result = database.run(
                            'select',
                            'controller_security',
                            ['password'],
                            "`ip` = %s FOR UPDATE",
                            [node['ip']]
                        )

                    r = luci.put(c['lib'], c['method'], c['params'], i + 10)

                    if c['method'] == 'user.setpasswd':
                        if r['error'] is None:
                            database.run(
                                'raw',
                                '''\
INSERT INTO controller_security
       (ip, password)
VALUES (%s, %s)
    ON DUPLICATE KEY UPDATE
       password = %s''',
                                [node['ip'], new_password, new_password])
                        database.commit()

                    with lock:
                        log.debug('[{}][{}][{}][{}][{}]'.format(
                            node['ip'],
                            c['method'],
                            '|'.join(c['params']),
                            r['result'],
                            r['error'],
                        ))

                    result.append(r)

                    j += 1
                error = False
                break
            except Exception as e:
                with lock:
                    log.error('[{}]'.format(e))
                error = True
                continue

        if not auth:
            result.append({'result': 'Authentication Failed'})
        elif error:
            result.append({'result': 'Connection Failed'})
        result_queue.put({
            'node': node,
            'result': result,
            'error': error,
        })
        node_queue.task_done()
    database.disconnect()
Beispiel #8
0
def pool(argv):
    import tempfile
    import subprocess
    import re
    from ams.sql import DataBase

    db = readCfg(cfgfile)['DataBase']

    database = DataBase(db)
    database.connect()
    poolList = database.run(
        'select', 'pool_config',
        ['name', 'address', 'user', 'worker', 'key', 'seckey']
    )

    with tempfile.NamedTemporaryFile(mode='w+', suffix='.ams') as temp:
        temp.write('#name\taddress\tuser\tworker\tkey\tseckey')
        if poolList:
            temp.write('\n')
            temp.write(
                '\n'.join('\t'.join(i for i in m if i is not None)
                          for m in poolList)
            )
        temp.write('\n')
        temp.flush()
        subprocess.call(['vim', temp.name])
        temp.seek(0)
        cfg = temp.readlines()

    pattern = re.compile(
        r'\s*(?P<name>btcchina|kano|ghash|cksolo)\s+'
        '(?P<address>[^\s]+)\s+'
        '(?P<user>[^\s]+)\s+'
        '(?P<worker>[^\s]+)\s+'
        '(?P<key>[^\s]+)'
        '(\s+(?P<seckey>[^\s]+))?\s*', re.X
    )

    result = []
    for c in cfg:
        if len(c.lstrip()) == 0 or c.lstrip()[0] == '#':
            continue
        match = re.match(pattern, c)
        if match is None:
            result = None
            break
        name = match.group('name')
        address = match.group('address')
        user = match.group('user')
        worker = match.group('worker')
        key = match.group('key')
        seckey = match.group('seckey')
        result.append({
            "name": name, "address": address, "user": user,
            "worker": worker, "key": key, "seckey": seckey
        })

    if result is None:
        print('Invalid configuration.')
        database.disconnect()
        exit()

    database.run('raw', 'DROP TABLES pool_config')
    database.run('create', 'pool_config', [
        {"name": "name", "type": "VARCHAR(16)"},
        {"name": "address", "type": "VARCHAR(64)"},
        {"name": "user", "type": "VARCHAR(64)"},
        {"name": "worker", "type": "VARCHAR(64)"},
        {"name": "key", "type": "VARCHAR(64)"},
        {"name": "seckey", "type": "VARCHAR(64)"}
    ])
    for r in result:
        database.run('insert', 'pool_config', list(r.keys()), list(r.values()))
    database.commit()
    database.disconnect()
Beispiel #9
0
def controller(argv):
    import tempfile
    import subprocess
    import re
    from ams.sql import DataBase

    db = readCfg(cfgfile)['DataBase']

    database = DataBase(db)
    database.connect()
    minerList = database.run(
        'select', 'controller_config',
        ['ip', 'port', 'mods', 'password']
    )

    with tempfile.NamedTemporaryFile(mode='w+', suffix='.ams') as temp:
        temp.write('#ip\tport\tmods\tpassword')
        if minerList:
            temp.write('\n')
            temp.write(
                '\n'.join('\t'.join(str(i) for i in m if i is not None)
                          for m in minerList)
            )
        temp.write('\n')
        temp.flush()
        subprocess.call(['vim', temp.name])
        temp.seek(0)
        cfg = temp.readlines()
    pattern = re.compile(
        r'\s*(?P<ip>[0-9a-fA-F.:\[\]]+)\s+'
        '(?P<port>[0-9]+)\s+'
        '(?P<mods>[0-9]+)\s+'
        '(?P<password>[^\s]+)?\s*', re.X
    )

    result = []
    for c in cfg:
        if len(c.lstrip()) == 0 or c.lstrip()[0] == '#':
            continue
        match = re.match(pattern, c)
        if match is None:
            result = None
            break
        ip = match.group('ip')
        port = int(match.group('port'))

        if not validIP(ip) or port > 65535:
            result = None
            break

        result.append({
            "ip": ip, "port": port,
            "mods": match.group('mods'),
            "password": match.group('password')
        })

    if result is None:
        print('Invalid configuration.')
        database.disconnect()
        exit()

    database.run('raw', 'DROP TABLES IF EXISTS controller_config')
    database.run('create', 'controller_config', [
        {"name": "ip", "type": "VARCHAR(40)"},
        {"name": "port", "type": "SMALLINT UNSIGNED"},
        {"name": "mods", "type": "SMALLINT UNSIGNED"},
        {"name": "password", "type": "VARCHAR(32)"}
    ])
    for r in result:
        database.run(
            'insert', 'controller_config', list(r.keys()), list(r.values()))
    database.commit()
    database.disconnect()
Beispiel #10
0
def config(argv):
    from ams.sql import DataBase
    from ams.luci import LuCI

    data = []
    if argv[1] == '-f':
        with open(argv[2], 'r') as f:
            for d in f.readlines():
                data.append({
                    'lib': d.split(' ')[0],
                    'method': d.split(' ')[1],
                    'param': [' '.join(d.split(' ')[2:])]
                })
    else:
        data.append({
            'lib': argv[1],
            'method': argv[2],
            'param': [argv[3]],
        })

    if argv[0] != "all":
        result = ipDecode(argv[0])
        if not result:
            exit()
        ip, port = result
        clause = "`ip` = '{}'".format(ip)

        db = readCfg(cfgfile)['DataBase']

        database = DataBase(db)
        database.connect()
        minerList = database.run(
            'select', 'controller_config', ['password'], clause)
        database.disconnect()
        if not minerList:
            exit()
        password = minerList[0][0]

        luci = LuCI(ip, port, password)
        luci.auth()
        for d in data:
            print(json.dumps(luci.put(d['lib'], d['method'], d['param'])))

    else:
        db = readCfg(cfgfile)['DataBase']
        database = DataBase(db)
        database.connect()
        minerList = database.run(
            'select', 'controller_config',
            ['ip', 'password']
        )
        database.disconnect()
        if not minerList:
            exit()
def before_request():
    g.database = DataBase(db)
    g.database.connect()
from ams.sql import DataBase

cfgfile = os.path.join(os.environ.get('VIRTUAL_ENV') or '/', 'etc/ams.conf')


def readCfg(filename):
    import configparser
    config = configparser.ConfigParser(interpolation=None)
    config.read(filename, encoding="utf8")
    return config


if __name__ == '__main__':
    cfg = readCfg(cfgfile)
    db = cfg['DataBase']
    database = DataBase(db)
    database.connect()

    columns = []

    for i in range(4):
        for j in range(18, 22):
            columns.append({
                'name': 'mw{}_{}'.format(i, j),
                'type': 'INT',
            })
            for name in ['ghsmm0', 'eratio']:
                columns.append({
                    'name': '{}{}_{}'.format(name, i, j),
                    'type': 'DOUBLE',
                })