Beispiel #1
0
def nfs_export_add(req,
                   host,
                   path,
                   options=None,
                   chown=None,
                   export_path=None):

    if not isinstance(options, list):
        if options is not None and len(options) > 0:
            options = [options]
        else:
            options = []

    if export_path is not None:
        raise TargetdError(
            TargetdError.NFS_NO_SUPPORT,
            "separate export path not supported at "
            "this time")
    bit_opt = 0
    key_opt = {}

    for o in options:
        if '=' in o:
            k, v = o.split('=')
            key_opt[k] = v
        else:
            bit_opt |= Export.bool_option[o]

    if chown is not None:
        if not allow_chown:
            raise TargetdError(
                TargetdError.NO_SUPPORT,
                "Chown is disabled. Consult manual before enabling it.")
        items = chown.split(':')
        try:
            uid = int(items[0])
            gid = -1
            if len(items) > 1:
                gid = int(items[1])
            os.chown(path, uid, gid)
        except ValueError as e:
            raise TargetdError(TargetdError.INVALID_ARGUMENT,
                               "Wrong chown arguments: {}".format(e))
    try:
        Nfs.export_add(host, path, bit_opt, key_opt)
    except ValueError as e:
        raise TargetdError(TargetdError.INVALID_ARGUMENT, "{}".format(e))
    return dict(host=host, path=path)
Beispiel #2
0
def _get_ss_by_uuid(req, fs_uuid, ss_uuid, fs_ht=None):
    if fs_ht is None:
        fs_ht = _get_fs_by_uuid(req, fs_uuid)

    for s in ss(req, fs_uuid, fs_ht):
        if s['uuid'] == ss_uuid:
            return s
    raise TargetdError(TargetdError.NOT_FOUND_SS, "snapshot not found")
Beispiel #3
0
def fs_create(req, pool_name, name, size_bytes):
    full_path = os.path.join(pool_name, fs_path, name)

    if not os.path.exists(full_path):
        invoke([fs_cmd, 'subvolume', 'create', full_path])
    else:
        raise TargetdError(TargetdError.EXISTS_FS_NAME,
                           'FS already exists (Btrfs)')
Beispiel #4
0
def _invoke_retries(command, throw_exception):
    # TODO take out this loop, used to handle bug in btrfs
    # ERROR: Failed to lookup path for root 0 - No such file or directory

    for i in range(0, 5):
        result, out, err = invoke(command, False)
        if result == 0:
            return result, out, err
        elif result == 19:
            time.sleep(1)
            continue
        else:
            raise TargetdError(-303, "Unexpected exit code %d" % result)

    raise TargetdError(
        -303, "Unable to execute command after "
        "multiple retries %s" % (str(command)))
Beispiel #5
0
def initialize(config_dict):

    global pools
    global allow_chown

    allow_chown = config_dict['allow_chown']

    all_fs_pools = list(config_dict['fs_pools'])

    for mount in all_fs_pools:
        if not os.path.exists(mount):
            raise TargetdError(TargetdError.NOT_FOUND_FS,
                               'The fs_pool {0} does not exist'.format(mount))

    for info in Mount.mounted_filesystems():
        if info[Mount.MOUNT_POINT] in all_fs_pools:
            filesystem = info[Mount.FS_TYPE]
            if filesystem in pool_modules:
                # forward both mountpoint and device to the backend as ZFS prefers its own devices (pool/volume) and
                # btrfs prefers mount points (/mnt/btrfs). Otherwise ZFS or btrfs needs to ask mounted_filesystems again
                pools[filesystem].append({
                    "mount": info[Mount.MOUNT_POINT],
                    "device": info[Mount.DEVICE]
                })
            else:
                raise TargetdError(
                    TargetdError.NO_SUPPORT,
                    'Unsupported filesystem {0} for pool {1}'.format(
                        info[2], info[1]))

    for modname, mod in pool_modules.items():
        mod.fs_initialize(config_dict, pools[modname])

    return dict(
        fs_list=fs,
        fs_destroy=fs_destroy,
        fs_create=fs_create,
        fs_clone=fs_clone,
        ss_list=ss,
        fs_snapshot=fs_snapshot,
        fs_snapshot_delete=fs_snapshot_delete,
        nfs_export_auth_list=nfs_export_auth_list,
        nfs_export_list=nfs_export_list,
        nfs_export_add=nfs_export_add,
        nfs_export_remove=nfs_export_remove,
    )
Beispiel #6
0
def pool_check(pool_name):
    """
    pool_name *cannot* be trusted, funcs taking a pool param must call
    this or to ensure passed-in pool name is one targetd has
    been configured to use.
    """
    if pool_name not in pools:
        raise TargetdError(-110, "Invalid filesystem pool")
Beispiel #7
0
def fs_create(req, pool_name, name, size_bytes):
    pool_check(pool_name)

    full_path = os.path.join(pool_name, fs_path, name)

    if not os.path.exists(full_path):
        invoke([fs_cmd, 'subvolume', 'create', full_path])
    else:
        raise TargetdError(-53, 'FS already exists')
Beispiel #8
0
def _json_payload(payload):
    assert payload.get('jsonrpc') == "2.0"
    if 'error' in payload:
        error_code = int(payload['error']['code'])
        if error_code <= 0:
            raise TargetdError(error_code, payload['error'].get('message', ''))
        else:
            raise Exception("Invalid error code %d, should be negative!" %
                            error_code)
    else:
        return payload['result']
Beispiel #9
0
def pool_module(pool_name):
    """
        Determines the module responsible for the given pool
        :param pool_name: the pool to determine this for
        :return: the module responsible for it
    """
    for modname, mod in pool_modules.items():
        if mod.has_fs_pool(pool_name):
            return mod
    raise TargetdError(TargetdError.INVALID_POOL,
                       "Invalid pool (%s)" % pool_name)
Beispiel #10
0
def nfs_export_remove(req, host, path):
    found = False

    for e in Nfs.exports():
        if e.host == host and e.path == path:
            Nfs.export_remove(e)
            found = True

    if not found:
        raise TargetdError(-400, "NFS export to remove not found %s:%s",
                           (host, path))
Beispiel #11
0
def nfs_export_remove(req, host, path):
    found = False

    for e in Nfs.exports():
        if e.host == host and e.path == path:
            Nfs.export_remove(e)
            found = True

    if not found:
        raise TargetdError(
            TargetdError.NOT_FOUND_NFS_EXPORT,
            "NFS export to remove not found %s:%s" % (host, path))
Beispiel #12
0
def fs_snapshot(req, pool, name, dest_ss_name):
    source_path = os.path.join(pool, fs_path, name)
    dest_base = os.path.join(pool, ss_path, name)
    dest_path = os.path.join(dest_base, dest_ss_name)

    create_sub_volume(dest_base)

    if os.path.exists(dest_path):
        raise TargetdError(TargetdError.EXISTS_FS_NAME,
                           "Snapshot already exists with that name (Btrfs)")

    invoke([fs_cmd, 'subvolume', 'snapshot', '-r', source_path, dest_path])
Beispiel #13
0
def fs_clone(req, fs_uuid, dest_fs_name, snapshot_id):
    fs_ht = _get_fs_by_uuid(req, fs_uuid)

    if not fs_ht:
        raise TargetdError(-104, "fs_uuid not found")

    if snapshot_id:
        snapshot = _get_ss_by_uuid(req, fs_uuid, snapshot_id)
        if not snapshot:
            raise TargetdError(-112, "snapshot not found")

        source = os.path.join(fs_ht['pool'], ss_path, fs_ht['name'],
                              snapshot['name'])
        dest = os.path.join(fs_ht['pool'], fs_path, dest_fs_name)
    else:
        source = os.path.join(fs_ht['pool'], fs_path, fs_ht['name'])
        dest = os.path.join(fs_ht['pool'], fs_path, dest_fs_name)

    if os.path.exists(dest):
        raise TargetdError(-51, "Filesystem with that name exists")

    invoke([fs_cmd, 'subvolume', 'snapshot', source, dest])
Beispiel #14
0
def fs_clone(req, pool, name, dest_fs_name, snapshot_name=None):
    if snapshot_name is not None:
        source = os.path.join(pool, ss_path, name, snapshot_name)
        dest = os.path.join(pool, fs_path, dest_fs_name)
    else:
        source = os.path.join(pool, fs_path, name)
        dest = os.path.join(pool, fs_path, dest_fs_name)

    if os.path.exists(dest):
        raise TargetdError(TargetdError.EXISTS_CLONE_NAME,
                           "Filesystem with that name exists (Btrfs)")

    invoke([fs_cmd, 'subvolume', 'snapshot', source, dest])
Beispiel #15
0
def fs_snapshot(req, fs_uuid, dest_ss_name):
    fs_ht = _get_fs_by_uuid(req, fs_uuid)

    if fs_ht:
        source_path = os.path.join(fs_ht['pool'], fs_path, fs_ht['name'])
        dest_base = os.path.join(fs_ht['pool'], ss_path, fs_ht['name'])
        dest_path = os.path.join(dest_base, dest_ss_name)

        create_sub_volume(dest_base)

        if os.path.exists(dest_path):
            raise TargetdError(-53, "Snapshot already exists with that name")

        invoke([fs_cmd, 'subvolume', 'snapshot', '-r', source_path, dest_path])
Beispiel #16
0
def nfs_export_add(req, host, path, export_path, options):

    if export_path is not None:
        raise TargetdError(
            -401, "separate export path not supported at "
            "this time")
    bit_opt = 0
    key_opt = {}

    for o in options:
        if '=' in o:
            k, v = o.split('=')
            key_opt[k] = v
        else:
            bit_opt |= Export.bool_option[o]

    Nfs.export_add(host, path, bit_opt, key_opt)
Beispiel #17
0
def rpc(method, params=None, data=None):
    global id_num
    auth_info = HTTPBasicAuth(user, password)

    if not data:
        data = json.dumps(
            dict(id=id_num, method=method, params=params,
                 jsonrpc="2.0")).encode('utf-8')

    id_num += 1
    url = "%s://%s:%s%s" % (proto, host, port, rpc_path)
    r = requests.post(url, data=data, auth=auth_info, verify=cert_file)
    if r.status_code == 200:
        # JSON RPC error
        return _json_payload(r.json())
    else:
        # Transport error
        raise TargetdError(r.status_code, str(r))
Beispiel #18
0
def _get_fs_by_uuid(req, fs_uuid):
    for f in fs(req):
        if f['uuid'] == fs_uuid:
            return f
    raise TargetdError(TargetdError.NOT_FOUND_FS, "fs_uuid not found")