Exemplo n.º 1
0
def discovery_wrapper(hostname=None,
                      discovery_method=None,
                      operation=None,
                      op_params=(),
                      discover=False):
    """
    Returns the iscsiadm command, with discovery mode,
    corresponding to different specified arguments
    """
    cmd = [ISCSIADM_BINARY, "-m", "discoverydb"]
    if hostname:
        cmd.extend(["-p", hostname])
    if discovery_method:
        cmd.extend(["-t", discovery_method])
    if operation:
        cmd.extend(["-o", operation])
        if op_params:
            cmd.extend(["-n", "discovery.sendtargets.auth.%s" % op_params[0]])
            cmd.extend(["-v", op_params[1]])
    elif discover:
        cmd.extend(["-D", "-P", "1"])
    return_code, output_success, output_failure = invoke(cmd, False)
    if return_code:
        try:
            error_string = output_failure.splitlines()[0].split(" ", 1)[-1]
            error_string = error_string.strip()
            # error_string extracts the text after "iscsiadm: " of the
            # first line of e.output
            error_code = get_error_code(return_code)
            raise TargetdError(error_code, error_string)
        except IndexError:
            raise TargetdError(DISCOVERY_RECORD_NOT_FOUND,
                               "No discovery records found")
    return output_success
Exemplo n.º 2
0
def fswrites(req, domain=None, operation=None, timeout=15):
    """Quiesce or unquiesce filesystem writes by a VM (domain).
    operation is "freeze" (quiesce) or "thaw" (unquiesce);
    timeout is optional, with a default of 15:
    to ensure that a VM is not left in a frozen state, if
    operation is "freeze" then a thaw will issue timeout seconds
    after running this program -
    a timeout of 0 means "no timeout".
    """
    if not domain:
        raise TargetdError(GENERAL_TARGETD_ERROR,
                           "Must specify a domain (VM).")
    if operation not in VIRSH_CMDS:
        raise TargetdError(GENERAL_TARGETD_ERROR,
                           "Unsupported operation (%r)." % operation)
    cmd = VIRSH_CMDS[operation] % domain
    log.debug("fswrites: %s" % cmd)
    subp = subprocess.Popen(cmd,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)
    out = subp.communicate()[0].strip()
    if subp.returncode:
        raise RuntimeError("%r returned %r: %r" % (cmd, subp.returncode, out))
    if operation == "freeze" and timeout != 0:
        thaw = VIRSH_CMDS["thaw"] % domain
        subprocess.Popen("sleep %s && %s" % (timeout, thaw), shell=True)
Exemplo n.º 3
0
def create_filtered_volume(req, handler=None, name=None, filters=None, device=None, serial=None):
    filters = filters or []
    handler = handler or "mp_filter_stack"
    if not name:
        raise TargetdError(GENERAL_TARGETD_ERROR, "No name specified.")
    err = _alnum(name, extras='_-')
    if err:
        raise TargetdError(GENERAL_TARGETD_ERROR, "%r: %s" % (name, err))
    if not (device or serial):
        raise TargetdError(GENERAL_TARGETD_ERROR, "No device specified.")
    if serial and not device:
        device = _device_from_serial(serial)
    if not device or not os.path.exists(device):
        raise TargetdError(GENERAL_TARGETD_ERROR, "Device not found.")

    _validate_filters(filters)
    filterstack = '>'.join(filters)
    if filterstack:
        filterstack += '>'
    config_str = handler + '/>' + filterstack + device
    filtered_dev = rtslib.UserBackedStorageObject(name, config=config_str,
            size=_device_size(device))
    log.debug("Created %s on %s" % (name, filterstack + device))
    tcm_loop = rtslib.FabricModule("loopback")
    target = rtslib.Target(tcm_loop)
    tpg = rtslib.TPG(target, 1)
    lun = rtslib.LUN(tpg, 0, filtered_dev)
    log.debug("Created loopback target %s on %s" % (target.wwn, name))
    for delay in range(1, 4):
        time.sleep(delay)
        dev = _device_from_wwn(filtered_dev.wwn)
        if dev:
            log.debug("Target %s is at %s" % (target.wwn, dev))
            return dev
Exemplo n.º 4
0
def validate_string(msg):
    """
    Raise an error if the specified string is empty,
    longer than 255 chars or not ASCII encoded
    """
    if len(msg) > 255:
        raise TargetdError(STRING_TOO_LONG, "String too long")
    elif msg == "":
        raise TargetdError(EMPTY_STRING, "Unauthorised empty string")
    try:
        msg.decode('ascii')
    except UnicodeDecodeError:
        raise TargetdError(NO_ASCSII_STRING,
                           "Not a ascii-encoded unicode string")
Exemplo n.º 5
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)))
Exemplo n.º 6
0
def node_wrapper(targetname=None,
                 hostname=None,
                 operation="",
                 op_params=(),
                 login_out=None):
    """
    Returns the iscsiadm command, with node mode,
    corresponding to different specified arguments
    """
    cmd = [ISCSIADM_BINARY, "-m", "node", "-P", "1"]
    if targetname:
        cmd.extend(["-T", targetname])
    if hostname:
        cmd.extend(["-p", hostname])
    if operation:
        cmd.extend(["-o", operation])
        if op_params:
            cmd.extend(["-n", "node.session.auth.%s" % op_params[0]])
            cmd.extend(["-v", op_params[1]])
    elif login_out:
        if login_out == "login":
            cmd.append("--login")
        if login_out == "logout":
            cmd.append("--logout")
    error_code, output_success, output_failure = invoke(cmd, False)
    if error_code != 0:
        error_string = output_failure.splitlines()[0].split(" ", 1)[-1].strip()
        # error_string extracts the text after "iscsiadm: " of the
        # first line of e.output
        error_code = get_error_code(error_code)
        raise TargetdError(error_code, error_string)
    return output_success
Exemplo n.º 7
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")
Exemplo n.º 8
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')
Exemplo n.º 9
0
def discover_portal(req,
                    hostname,
                    discovery_method="sendtargets",
                    auth_method=None,
                    username=None,
                    password=None,
                    username_in=None,
                    password_in=None):
    """
    Discover all targets for a given discovery portal
    using specified informations
    """
    validate_string(hostname)
    if discovery_method not in DISCOVERY_METHODS:
        raise TargetdError(
            INVALID_VALUE_DISCOVERY, "Invalid value."
            " Possible values are : %s" % ", ".join(DISCOVERY_METHODS))

    if auth_method in AUTH_METHODS:
        validate_string(username)
        validate_string(password)
        discovery_wrapper(hostname, discovery_method, "new")
        discovery_wrapper(hostname, discovery_method, "update",
                          ("authmethod", "CHAP"))
        discovery_wrapper(hostname, discovery_method, "update",
                          ("username", username))
        discovery_wrapper(hostname, discovery_method, "update",
                          ("password", password))
        if auth_method == "mutual_chap":
            validate_string(username_in)
            validate_string(password_in)
            discovery_wrapper(hostname, discovery_method, "update",
                              ("username_in", username_in))
            discovery_wrapper(hostname, discovery_method, "update",
                              ("password_in", password_in))
    elif auth_method:
        raise TargetdError(
            INVALID_VALUE_AUTH, "Invalid value."
            " Possible values are : %s" % ", ".join(AUTH_METHODS))

    output = discovery_wrapper(hostname, discovery_method, discover=True)

    return node_summary_parser(output)
Exemplo n.º 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))
Exemplo n.º 11
0
def delete_filtered_volume(req, name=None):
    if not name:
        raise TargetdError(GENERAL_TARGETD_ERROR, "No name specified.")
    root = rtslib.RTSRoot()
    stores = [obj for obj in root.storage_objects if obj.name == name
            and obj.plugin == 'user']
    if len(stores) != 1:
        raise TargetdError(GENERAL_TARGETD_ERROR,
                "%d backstores with name %r." % (len(stores), name))
    targets = {}
    for target in root.targets:
        for tpg in target.tpgs:
            for lun in tpg.luns:
                if lun.storage_object.name == name:
                    targets[target] = 1
    for target in targets.keys():
        log.debug("Deleting loopback target %s for %s." % (target.wwn, name))
        target.delete()
    log.debug("Deleting %s." % name)
    stores[0].delete()
Exemplo n.º 12
0
def fs_clone(req, fs_uuid, dest_fs_name, snapshot_id):
    fs = _get_fs_by_uuid(req, fs_uuid)

    if not fs:
        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['pool'], ss_path, fs['name'], snapshot['name'])
        dest = os.path.join(fs['pool'], fs_path, dest_fs_name)
    else:
        source = os.path.join(fs['pool'], fs_path, fs['name'])
        dest = os.path.join(fs['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])
Exemplo n.º 13
0
def delete_discovery(req, hostname, discovery_method="sendtargets"):
    """
    Delete discovery of targets at the specified hostname
    with the right discovery method
    """
    validate_string(hostname)
    if discovery_method not in DISCOVERY_METHODS:
        raise TargetdError(
            INVALID_VALUE_DISCOVERY, "Invalid value."
            " Possible values are : %s" % ", ".join(DISCOVERY_METHODS))

    output = discovery_wrapper(hostname, discovery_method, "delete")
Exemplo n.º 14
0
def display_discovery(req, hostname, discovery_method="sendtargets"):
    """
    Returns a dictionary of all data for the
    discovery portal at the specified hostname
    """
    validate_string(hostname)
    if discovery_method not in DISCOVERY_METHODS:
        raise TargetdError(
            INVALID_VALUE_DISCOVERY, "Invalid value."
            " Possible values are : %s" % ", ".join(DISCOVERY_METHODS))

    output = discovery_wrapper(hostname, discovery_method)
    return discovery_node_parser(output, "discovery")
Exemplo n.º 15
0
def fs_snapshot(req, fs_uuid, dest_ss_name):
    fs = _get_fs_by_uuid(req, fs_uuid)

    if fs:
        source_path = os.path.join(fs['pool'], fs_path, fs['name'])
        dest_base = os.path.join(fs['pool'], ss_path, fs['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])
Exemplo n.º 16
0
def display_session(req, targetname=None, hostname=None):
    """
    Returns a dictionary of all data for all active sessions
    If a session is specified, returns a dictionary of all data
    for the given session using specified informations
    """
    output = session_wrapper()
    d = session_parser(output)
    if targetname and hostname:
        validate_string(targetname)
        validate_string(hostname)
        try:
            return {targetname: {hostname: d[targetname][hostname]}}
        except KeyError:
            raise TargetdError(NO_SESSION_INFO, "Could not get session info")
    elif targetname:
        validate_string(targetname)
        try:
            return {targetname: d[targetname]}
        except KeyError:
            raise TargetdError(NO_SESSION_INFO, "Could not get session info")
    else:
        return d
Exemplo n.º 17
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)
Exemplo n.º 18
0
def session_wrapper(session_id=None):
    """
    Returns the iscsiadm command, with session mode,
    corresponding to different specified arguments
    """
    cmd = [ISCSIADM_BINARY, "-m", "session", "-P", "1"]
    if session_id:
        cmd.extend(["-r", session_id])
    error_code, output_success, output_failure = invoke(cmd, False)
    if error_code != 0:
        error_string = output_failure.splitlines()[0].split(" ", 1)[-1].strip()
        # error_string extracts the text after "iscsiadm: " of the
        # first line of e.output
        error_code = get_error_code(error_code)
        raise TargetdError(error_code, error_string)
    return output_success
Exemplo n.º 19
0
def login_target(req,
                 targetname,
                 hostname,
                 auth_method=None,
                 username=None,
                 password=None,
                 username_in=None,
                 password_in=None):
    """
    Login to a given target using specified informations
    """
    validate_string(targetname)
    validate_string(hostname)
    # allow for the possibility that we're already logged in
    devices = glob.glob("/dev/disk/by-path/*%s:*%s-lun-*" %
                        (hostname, targetname))
    if len(devices) == 1:
        return os.path.realpath(devices[0])
    if auth_method in AUTH_METHODS:
        validate_string(username)
        validate_string(password)
        node_wrapper(targetname, hostname, "update", ("authmethod", "CHAP"))
        node_wrapper(targetname, hostname, "update", ("username", username))
        node_wrapper(targetname, hostname, "update", ("password", password))
        if auth_method == "mutual_chap":
            validate_string(username_in)
            validate_string(password_in)
            node_wrapper(targetname, hostname, "update",
                         ("username_in", username_in))
            node_wrapper(targetname, hostname, "update",
                         ("password_in", password_in))
    elif auth_method:
        raise TargetdError(
            INVALID_VALUE_AUTH, "Invalid value."
            " Possible values are : %s" % ", ".join(AUTH_METHODS))
    node_wrapper(targetname, hostname, login_out="login")
    for delay in range(4):
        time.sleep(delay)
        devices = glob.glob("/dev/disk/by-path/*%s:*%s-lun-*" %
                            (hostname, targetname))
        if len(devices) == 1:
            return os.path.realpath(devices[0])
Exemplo n.º 20
0
def _validate_filters(filters):
    for filt in filters:
        err = _alnum(filt, extras='_-')
        if err:
            raise TargetdError(GENERAL_TARGETD_ERROR, "%r: %s" % (filt, err))