Beispiel #1
0
def get_seed():
    current_app.logger.info("Fetch seed from MineBD.")
    # Get wallet seed from MineBD.
    seed = None
    mbdata, mb_status_code = get_from_minebd('siawalletseed')
    if mb_status_code == 200:
        seed = mbdata["message"]
    return seed
Beispiel #2
0
def api_status():
    # Doc: https://bitbucket.org/mineboxgmbh/minebox-client-tools/src/master/doc/mb-ui-gateway-api.md#markdown-header-get-status
    username = check_login()
    outdata = {}
    if username:
        outdata["logged_in"] = True
        outdata["user"] = username
    else:
        outdata["logged_in"] = False
        outdata["user"] = None

    mbdata, mb_status_code = get_from_minebd('status')
    if mb_status_code == 200:
        outdata["minebd_running"] = True
        outdata["minebd_encrypted"] = mbdata["hasEncryptionKey"]
        outdata["minebd_storage_mounted"] = ismount(MINEBD_STORAGE_PATH)
        outdata["restore_running"] = mbdata["restoreRunning"]
        outdata["restore_progress"] = mbdata["completedRestorePercent"]
    else:
        outdata["minebd_running"] = False
        outdata["minebd_encrypted"] = None
        outdata["minebd_storage_mounted"] = False
        outdata["restore_running"] = False
        outdata["restore_progress"] = None

    hasusers = False
    for user in pwd.getpwall():
        if user.pw_uid >= 1000 and user.pw_uid < 65500 and user.pw_name != "sia":
            hasusers = True
    outdata["users_created"] = hasusers

    if 'DEMO' in environ:
        outdata["backup_type"] = "sia_demo"
    else:
        outdata["backup_type"] = "sia"
    consdata, cons_status_code = get_from_sia('consensus')
    if cons_status_code == 200:
        outdata["sia_daemon_running"] = True
        outdata["consensus_height"] = consdata["height"]
        outdata["consensus_synced"] = consdata["synced"]
    else:
        outdata["sia_daemon_running"] = False
        outdata["consensus_height"] = None
        outdata["consensus_synced"] = None
    walletdata, wallet_status_code = get_from_sia('wallet')
    if username and wallet_status_code == 200:
        outdata["wallet_unlocked"] = walletdata["unlocked"]
        outdata["wallet_encrypted"] = walletdata["encrypted"]
        outdata["wallet_confirmed_balance_sc"] = int(walletdata["confirmedsiacoinbalance"]) / H_PER_SC
        outdata["wallet_unconfirmed_delta_sc"] = (int(walletdata["unconfirmedincomingsiacoins"]) -
                                                  int(walletdata["unconfirmedoutgoingsiacoins"])) / H_PER_SC

    else:
        outdata["wallet_unlocked"] = None
        outdata["wallet_encrypted"] = None
        outdata["wallet_confirmed_balance_sc"] = None
        outdata["wallet_unconfirmed_delta_sc"] = None
    return jsonify(outdata), 200
Beispiel #3
0
def check_backup_prerequisites():
    # Check if prerequisites are met to make backups.
    success, errmsg = check_sia_sync()
    if not success:
        return False, errmsg
    siadata, sia_status_code = get_from_sia("renter/contracts")
    if sia_status_code >= 400:
        return False, siadata["message"]
    if not siadata["contracts"]:
        return False, "No Sia renter contracts, so uploading is not possible."
    mbdata, mb_status_code = get_from_minebd('status')
    if mb_status_code >= 400:
        return False, mbdata["message"]
    if mbdata["restoreRunning"] and mbdata["completedRestorePercent"] < 100:
        return False, "MineBD is running an incomplete restore, so creating a backup is not possible."
    # Potentially check things other than sia.
    return True, ""
Beispiel #4
0
def api_key_put():
    # Doc: https://bitbucket.org/mineboxgmbh/minebox-client-tools/src/master/doc/mb-ui-gateway-api.md#markdown-header-put-key
    mbdata, mb_status_code = get_from_minebd('status')
    if mb_status_code == 200:
        if mbdata["hasEncryptionKey"]:
            return jsonify(message="File system is already encrypted, cannot set key."), 400
        # MineBD is running but encryption is not yet set up, we can actually set a key!
        if len(request.data):
          retcode = subprocess.call([SUDO, MBKEY_CMD, "set", request.data])
          if retcode == 0:
              return jsonify(message="Key set successfully"), 200
          else:
              return jsonify(message="Setting key failed."), 500
        else:
            return jsonify(message="No useful key handed over."), 400
    else:
        return jsonify(message="The Minebox storage is not running, please reboot the box or call support!"), 503
Beispiel #5
0
def api_status():
    # Doc: https://bitbucket.org/mineboxgmbh/minebox-client-tools/src/master/doc/mb-ui-gateway-api.md#markdown-header-get-status
    username = check_login()
    outdata = {}
    outdata["hostname"] = uname()[1]
    if username:
        outdata["logged_in"] = True
        outdata["user"] = username
    else:
        outdata["logged_in"] = False
        outdata["user"] = None

    mbdata, mb_status_code = get_from_minebd('status')
    if mb_status_code == 200:
        outdata["minebd_running"] = True
        outdata["minebd_encrypted"] = mbdata["hasEncryptionKey"]
        outdata["minebd_storage_mounted"] = ismount(MINEBD_STORAGE_PATH)
        ST_RDONLY = 1  # In Python >= 3.2, we could use os.ST_RDONLY directly instead.
        outdata["minebd_storage_mount_readonly"] = bool(
            os.statvfs(MINEBD_STORAGE_PATH).f_flag & ST_RDONLY)
        outdata["restore_running"] = mbdata["restoreRunning"]
        outdata["restore_progress"] = mbdata["completedRestorePercent"]
    else:
        outdata["minebd_running"] = False
        outdata["minebd_encrypted"] = None
        outdata["minebd_storage_mounted"] = False
        outdata["minebd_storage_mount_readonly"] = None
        outdata["restore_running"] = False
        outdata["restore_progress"] = None

    hasusers = False
    for user in pwd.getpwall():
        if (user.pw_uid >= 1000 and user.pw_uid < 65500
                and user.pw_name != "sia" and not user.pw_name.endswith("$")):
            hasusers = True
    outdata["users_created"] = hasusers
    # Only used by minebox-ui which requires minebox-rockstor
    if is_rockstor_system():
        outdata["user_setup_complete"] = rockstor_user_setup()

    if 'DEMO' in environ:
        outdata["backup_type"] = "sia_demo"
    else:
        outdata["backup_type"] = "sia"
    consdata, cons_status_code = get_from_sia('consensus')
    if cons_status_code == 200:
        outdata["sia_daemon_running"] = True
        outdata["consensus_height"] = consdata["height"]
        outdata["consensus_synced"] = consdata["synced"]
    else:
        outdata["sia_daemon_running"] = False
        outdata["consensus_height"] = None
        outdata["consensus_synced"] = None
    walletdata, wallet_status_code = get_from_sia('wallet')
    if username and wallet_status_code == 200:
        outdata["wallet_unlocked"] = walletdata["unlocked"]
        outdata["wallet_encrypted"] = walletdata["encrypted"]
        outdata["wallet_confirmed_balance_sc"] = int(
            walletdata["confirmedsiacoinbalance"]) / H_PER_SC
        outdata["wallet_unconfirmed_delta_sc"] = (
            int(walletdata["unconfirmedincomingsiacoins"]) -
            int(walletdata["unconfirmedoutgoingsiacoins"])) / H_PER_SC

    else:
        outdata["wallet_unlocked"] = None
        outdata["wallet_encrypted"] = None
        outdata["wallet_confirmed_balance_sc"] = None
        outdata["wallet_unconfirmed_delta_sc"] = None
    return jsonify(outdata), 200
Beispiel #6
0
def api_key_generate():
    # Doc: https://bitbucket.org/mineboxgmbh/minebox-client-tools/src/master/doc/mb-ui-gateway-api.md#markdown-header-get-keygenerate
    mbdata, mb_status_code = get_from_minebd('keys/asJson')
    # For the moment, just blindly hand over the result from MineBD.
    return jsonify(mbdata), mb_status_code
Beispiel #7
0
def initiate_uploads(status):
    current_app.logger.info('Starting uploads.')
    status["message"] = "Starting uploads"
    status["step"] = sys._getframe().f_code.co_name.replace("_", " ")
    status["starttime_step"] = time.time()
    snapname = status["snapname"]
    backupname = status["backupname"]

    metadir = path.join(METADATA_BASE, backupname)
    bfinfo_path = path.join(metadir, INFO_FILENAME)
    if path.isfile(bfinfo_path):
        remove(bfinfo_path)
    sia_filedata, sia_status_code = get_from_sia('renter/files')
    if sia_status_code == 200:
        siafiles = sia_filedata["files"]
    else:
        return False, "ERROR: sia daemon needs to be running for any uploads."

    # We have a randomly named subdirectory containing the .dat files.
    # The subdirectory matches the serial number that MineBD returns.
    mbdata, mb_status_code = get_from_minebd('serialnumber')
    if mb_status_code == 200:
        mbdirname = mbdata["message"]
    else:
        return False, "ERROR: Could not get serial number from MineBD."

    status["backupfileinfo"] = []
    status["backupfiles"] = []
    status["uploadfiles"] = []
    status["backupsize"] = 0
    status["uploadsize"] = 0
    status["min_redundancy"] = None
    status["earliest_expiration"] = None
    for filepath in glob(
            path.join(DATADIR_MASK, 'snapshots', snapname, mbdirname,
                      '*.dat')):
        fileinfo = stat(filepath)
        # Only use files of non-zero size.
        if fileinfo.st_size:
            filename = path.basename(filepath)
            (froot, fext) = path.splitext(filename)
            sia_fname = '%s.%s%s' % (froot, int(fileinfo.st_mtime), fext)
            if sia_fname in status["backupfiles"]:
                # This file is already in the list, and we probably have
                # multiple lower disks, so omit this file.
                continue
            status["backupfiles"].append(sia_fname)
            status["backupsize"] += fileinfo.st_size
            if (siafiles and any(sf["siapath"] == sia_fname and sf["available"]
                                 and sf["redundancy"] > REDUNDANCY_LIMIT
                                 for sf in siafiles)):
                current_app.logger.info(
                    "%s is part of the set and already uploaded." % sia_fname)
            elif (siafiles
                  and any(sf["siapath"] == sia_fname for sf in siafiles)):
                status["uploadsize"] += fileinfo.st_size
                status["uploadfiles"].append(sia_fname)
                current_app.logger.info(
                    "%s is part of the set and the upload is already in progress."
                    % sia_fname)
            else:
                status["uploadsize"] += fileinfo.st_size
                status["uploadfiles"].append(sia_fname)
                current_app.logger.info(
                    "%s has to be uploaded, starting that." % sia_fname)
                siadata, sia_status_code = post_to_sia(
                    'renter/upload/%s' % sia_fname, {'source': filepath})
                if sia_status_code != 204:
                    return False, ("ERROR: sia upload error %s: %s" %
                                   (sia_status_code, siadata["message"]))
            status["backupfileinfo"].append({
                "siapath": sia_fname,
                "size": fileinfo.st_size
            })

    if not status["backupfiles"]:
        return False, "ERROR: The backup set has no files, that's impossible."
    with open(bfinfo_path, 'w') as outfile:
        json.dump(status["backupfileinfo"], outfile)
    return True, ""