From e260b8f2696f276887d17bf5fdcd5bf9f18e9475 Mon Sep 17 00:00:00 2001 From: lza_menace Date: Sun, 20 Sep 2020 22:03:22 -0700 Subject: [PATCH] setup docker! --- requirements.txt | 1 + wowstash/blueprints/meta/routes.py | 6 ++- wowstash/factory.py | 75 -------------------------- wowstash/library/docker.py | 85 ++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 77 deletions(-) create mode 100644 wowstash/library/docker.py diff --git a/requirements.txt b/requirements.txt index e5ccc72..cadbf53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ flask-login qrcode Pillow git+https://github.com/lalanza808/MoneroPy +docker diff --git a/wowstash/blueprints/meta/routes.py b/wowstash/blueprints/meta/routes.py index 91cb98c..1502618 100644 --- a/wowstash/blueprints/meta/routes.py +++ b/wowstash/blueprints/meta/routes.py @@ -3,6 +3,7 @@ from wowstash.blueprints.meta import meta_bp from wowstash.library.jsonrpc import daemon from wowstash.library.cache import cache from wowstash.library.db import Database +from wowstash.library.docker import Docker @meta_bp.route('/') @@ -24,8 +25,9 @@ def privacy(): @meta_bp.route('/health') def health(): return make_response(jsonify({ - 'cache': info.redis.ping(), - 'db': Database().connected + 'redis': cache.redis.ping(), + 'postgres': Database().connected, + 'docker': Docker().client.ping() }), 200) # @app.errorhandler(404) diff --git a/wowstash/factory.py b/wowstash/factory.py index ff79fae..0279619 100644 --- a/wowstash/factory.py +++ b/wowstash/factory.py @@ -75,81 +75,6 @@ def create_app(): from wowstash.library.jsonrpc import from_atomic return from_atomic(a) - # commands - @app.cli.command('create_wallets') - def create_wallets(): - import subprocess - from os import makedirs, path - from moneropy import account - from wowstash import config - from wowstash.factory import db - from wowstash.models import User - from wowstash.library.jsonrpc import daemon - - if not path.isdir(config.WALLET_DIR): - makedirs(config.WALLET_DIR) - - wallets_to_create = User.query.filter_by(wallet_created=False) - if wallets_to_create: - for u in wallets_to_create: - print(f'Creating wallet for user {u}') - seed, sk, vk, addr = account.gen_new_wallet() - command = f"""wownero-wallet-cli \ - --generate-new-wallet {config.WALLET_DIR}/{u.id}.wallet \ - --restore-height {daemon.info()['height']} \ - --password {u.wallet_password} \ - --mnemonic-language English \ - --daemon-address {config.DAEMON_PROTO}://{config.DAEMON_HOST}:{config.DAEMON_PORT} \ - --daemon-login {config.DAEMON_USER}:{config.DAEMON_PASS} \ - --command version - """ - proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE) - proc.communicate() - if proc.returncode == 0: - print(f'Successfully created wallet for {u}!') - u.wallet_created = True - db.session.commit() - else: - print(f'Failed to create wallet for {u}.') - - @app.cli.command('refresh_wallets') - def refresh_wallets(): - import subprocess - from os import kill - from moneropy import account - from wowstash import config - from wowstash.factory import db - from wowstash.models import User - from wowstash.library.jsonrpc import daemon - - users = User.query.all() - for u in users: - print(f'Refreshing wallet for {u}') - - if u.wallet_pid is None: - break - - # first check if the pid is still there - try: - kill(u.wallet_pid, 0) - except OSError: - print('pid does not exist') - u.wallet_connected = False - u.wallet_pid = None - u.wallet_connect_date = None - u.wallet_port = None - db.session.commit() - - # then check if the user session is still active - if u.is_active is False: - print('user session inactive') - kill(u.wallet_pid, 9) - u.wallet_connected = False - u.wallet_pid = None - u.wallet_connect_date = None - u.wallet_port = None - db.session.commit() - # Routes from wowstash.blueprints.auth import auth_bp from wowstash.blueprints.wallet import wallet_bp diff --git a/wowstash/library/docker.py b/wowstash/library/docker.py new file mode 100644 index 0000000..984110f --- /dev/null +++ b/wowstash/library/docker.py @@ -0,0 +1,85 @@ +from docker import from_env, APIClient +from docker.errors import NotFound +from socket import socket +from wowstash import config +from wowstash.models import User +from wowstash.library.jsonrpc import daemon + +class Docker(object): + def __init__(self): + self.client = from_env() + self.wownero_image = getattr(config, 'WOWNERO_IMAGE', 'lalanza808/wownero') + self.wallet_dir = getattr(config, 'WALLET_DIR', './data/wallets') + self.listen_port = 34569 + + def create_wallet(self, user_id): + u = User.query.get(user_id) + command = f"""wownero-wallet-cli \ + --generate-new-wallet /wallet/{u.id}.wallet \ + --restore-height {daemon.info()['height']} \ + --password {u.wallet_password} \ + --mnemonic-language English \ + --daemon-address {config.DAEMON_PROTO}://{config.DAEMON_HOST}:{config.DAEMON_PORT} \ + --daemon-login {config.DAEMON_USER}:{config.DAEMON_PASS} \ + --log-file /wallet/{u.id}-create.log + --command version + """ + container = self.client.containers.run( + self.wownero_image, + command=command, + auto_remove=True, + name=f'create_wallet_{u.id}', + remove=True, + detach=True, + volumes={ + f'{self.wallet_dir}/{u.id}': { + 'bind': '/wallet', + 'mode': 'rw' + } + } + ) + return container.short_id + + def start_wallet(self, user_id): + u = User.query.get(user_id) + command = f"""wownero-wallet-rpc \ + --non-interactive \ + --rpc-bind-port {self.listen_port} \ + --wallet-file /wallet/{u.id}.wallet \ + --rpc-login {u.id}:{u.wallet_password} \ + --password {u.wallet_password} \ + --daemon-address {config.DAEMON_PROTO}://{config.DAEMON_HOST}:{config.DAEMON_PORT} \ + --daemon-login {config.DAEMON_USER}:{config.DAEMON_PASS} \ + --log-file /wallet/{u.id}-rpc.log + """ + container = self.client.containers.run( + self.wownero_image, + command=command, + auto_remove=True, + name=f'start_wallet_{u.id}', + remove=True, + detach=True, + ports={ + f'{self.listen_port}/tcp': None + }, + volumes={ + f'{self.wallet_dir}/{u.id}': { + 'bind': '/wallet', + 'mode': 'rw' + } + } + ) + return container.short_id + + def get_port(self, container_id): + client = APIClient() + port_data = client.port(container_id, self.listen_port) + host_port = port_data[0]['HostPort'] + return int(host_port) + + def container_exists(self, container_id): + try: + self.client.containers.get(container_id) + return True + except NotFound: + return False