Пример #1
0
def do_detach_volume(oci_session, iscsiadm_session, iqn):
    """
    Detach the volume with given IQN

    Parameters
    ----------
    oci_session: OCISession
        The iscsiadm session.
    iscsiadm_session:
        iscsiadm.session()
    ocid: str
        The OCID.

    Returns
    -------
        None
    Raise
    -----
        Exception : when destroy has failed
    """

    _volume = get_volume_by_iqn(oci_session, iqn)
    if _volume is None:
        raise Exception("Volume with IQN [%s] not found" % iqn)

    try:
        _logger.info("Detaching volume %s (%s)", _volume.get_display_name(),
                     _volume.get_iqn())
        _volume.detach()
    except OCISDKError as e:
        _logger.debug("Failed to disconnect volume", exc_info=True)
        raise Exception("Failed to disconnect volume %s: %s" % iqn) from e

    _logger.debug('Volume detached, detaching it from iSCSI session')
    if not iscsiadm.detach(iscsiadm_session[iqn]['persistent_portal_ip'],
                           iscsiadm_session[iqn]['persistent_portal_port'],
                           iqn):
        raise Exception("Failed to detach target %s" % iqn)
def main():
    """
    Main.

    Returns
    -------
        int
            Return value of the operation, if any.
            0 otherwise.
    """
    global USE_OCI_SDK
    global oci_sdk_error
    global _user_euid
    oci_sdk_error = None
    oci_sess = None

    args = parse_args()

    _user_euid = os.geteuid()

    if oci_utils.oci_api.HAVE_OCI_SDK:
        try:
            oci_sess = oci_utils.oci_api.OCISession()
            USE_OCI_SDK = True
        except Exception as e:
            oci_sdk_error = str(e)
            USE_OCI_SDK = False
            if args.debug:
                raise

    if not os.path.isfile("/var/run/ocid.pid"):
        _logger.error("Warning:\n"
                      "For full functionality of this utility the ocid "
                      "service must be running\n"
                      "The administrator can start it using this command:\n"
                      "    sudo systemctl start ocid.service\n")

    max_volumes = OCIUtilsConfiguration.getint('iscsi', 'max_volumes')
    if max_volumes > oci_utils._MAX_VOLUMES_LIMIT:
        _logger.error(
            "Your configured max_volumes(%s) is over the limit(%s)\n"
            % (max_volumes, oci_utils._MAX_VOLUMES_LIMIT))
        max_volumes = oci_utils._MAX_VOLUMES_LIMIT

    ocid_cache = load_cache(iscsiadm.ISCSIADM_CACHE,
                            max_age=timedelta(minutes=2))[1]
    if ocid_cache is None and _user_euid == 0:
        # run ocid once, to update the cache
        ocid_refresh(wait=True, debug=args.debug)
        # now try to load again
        ocid_cache = load_cache(iscsiadm.ISCSIADM_CACHE,
                                max_age=timedelta(minutes=2))[1]
    if ocid_cache is None:
        targets, attach_failed = None, None
    else:
        targets, attach_failed = ocid_cache
    disks = lsblk.list()
    session = iscsiadm.session()
    detached = load_cache(__ignore_file)[1]
    if detached is None:
        detached = []

    if args.create_volume:
        if _user_euid != 0:
            _logger.error("You must run this program with root privileges "
                             "to create and attach iSCSI devices.\n")
            return 1
        if len(disks) > max_volumes:
            _logger.error(
                "This instance reached the max_volumes(%s)\n" % max_volumes)
            return 1

        # FIXME: use_chap
        retval = do_create_volume(oci_sess, size=args.create_volume,
                                  display_name=args.volume_name)
    elif args.destroy_volume:
        if _user_euid != 0:
            _logger.error("You must run this program with root privileges "
                             "to destroy a iSCSI volume.\n")
            return 1
        retval = do_destroy_volume(oci_sess, args.destroy_volume,
                                   args.interactive)
        if retval == 0:
            print "Volume %s is destroyed." % args.destroy_volume
        return retval

    elif args.detach_iqns:
        if _user_euid != 0:
            _logger.error("You must run this program with root privileges "
                             "to detach iSCSI devices.\n")
            return 1

        write_ignore_file = False
        retval = 0
        do_refresh = False
        for iqn in args.detach_iqns:
            if not iqn.startswith("iqn."):
                _logger.error("Invalid IQN %s\n" % iqn)
                retval = 1
                continue
            if iqn in detached:
                _logger.error("Target %s is already detached\n" % iqn)
                retval = 1
                continue
            if iqn not in session:
                _logger.error("Target %s not found\n" % iqn)
                retval = 1
                continue
            if 'boot:uefi' in iqn:
                _logger.error("IQN %s is the boot device, cannot "
                                 "detach.\n" % iqn)
                retval = 1
                continue
            if not unmount_device(session, iqn, disks):
                if args.interactive:
                    cont = ask_yes_no("Failed to unmount volume.  "
                                      "Continue detaching anyway?")
                    if not cont:
                        return 1
                else:
                    return 1

            api_detached = False

            if USE_OCI_SDK:
                api_detached = api_detach(oci_sess, iqn)

            if not iscsiadm.detach(session[iqn]['persistent_portal_ip'],
                                   session[iqn]['persistent_portal_port'],
                                   iqn):
                _logger.error("Failed to detach target %s\n" % iqn)
                retval = 1
            else:
                if not api_detached:
                    detached.append(iqn)
                    write_ignore_file = True
                    do_refresh = True
        if write_ignore_file:
            _logger.error("Updating ignore file: %s\n" % detached)
            write_cache(cache_content=detached,
                        cache_fname=__ignore_file)
        if do_refresh:
            ocid_refresh(debug=args.debug)
        return retval

    elif args.attach_iqns:
        if _user_euid != 0:
            _logger.error("You must run this program with root "
                             "privileges to attach iSCSI devices.\n")
            return 1

        if len(disks) > max_volumes:
            _logger.error(
                "This instance reached the max_volumes(%s)\n" % max_volumes)
            return 1

        retval = 0
        write_ignore_file = False
        do_refresh = False

        for iqn in args.attach_iqns:
            if iqn.startswith('ocid1.volume.oc'):
                # it's an OCID
                if not do_attach_ocid(oci_sess, iqn):
                    retval = 1
                continue
            elif not iqn.startswith("iqn."):
                _logger.error("Invalid IQN %s \n" % iqn)
                retval = 1
                continue

            if iqn in session:
                print "Target %s is already attached." % iqn
                continue
            if iqn not in detached and iqn not in attach_failed:
                _logger.error("Target %s not found\n" % iqn)
                retval = 1
                continue
            user = args.username
            passwd = args.password
            if user is None or passwd is None:
                (user, passwd) = get_chap_secret(iqn)
            if do_attach(oci_sess, iqn, targets,
                         user=user, passwd=passwd) != 0:
                _logger.error("Failed to attach target %s\n" % iqn)
                retval = 1
            else:
                do_refresh = True
                if iqn in detached:
                    detached.remove(iqn)
                if args.username is not None:
                    save_chap_secret(iqn, args.username, args.password)
                write_ignore_file = True
        if write_ignore_file:
            write_cache(cache_content=detached,
                        cache_fname=__ignore_file)
        if do_refresh:
            ocid_refresh(debug=args.debug)

        return retval

    if args.show:
        display_current_devices(oci_sess, session, disks)
        api_display_available_devices(oci_sess, args)

    if args.create_volume or args.destroy_volume:
        return retval

    if detached:
        print
        print "Detached devices:"

        do_refresh = False
        write_ignore_file = False
        for iqn in detached:
            display_detached_device(iqn, targets)
            if args.interactive:
                if _user_euid != 0:
                    print "You must run this program with root privileges " \
                          "to attach iSCSI devices.\n"
                    ans = False
                else:
                    ans = ask_yes_no("Would you like to attach this device?")
                if ans:
                    retval = do_attach(oci_sess, iqn, targets)
                    do_refresh = True
                    if retval == 24:
                        # authentication error
                        attach_failed[iqn] = 24
                    if iqn in detached:
                        detached.remove(iqn)
                        write_ignore_file = True
        if write_ignore_file:
            write_cache(cache_content=detached,
                        cache_fname=__ignore_file)
        if do_refresh:
            ocid_refresh(debug=args.debug)

    if attach_failed:
        print
        print "Devices that could not be attached automatically:"

        auth_errors = 0
        for iqn in attach_failed.keys():
            if attach_failed[iqn] == 24:
                auth_errors += 1

        for iqn in attach_failed.keys():
            display_attach_failed_device(iqn, targets, attach_failed)
            do_refresh = False
            if args.interactive:
                if attach_failed[iqn] != 24:
                    # not authentication error
                    ans = True
                    while ans:
                        if _user_euid != 0:
                            print "You must run this program with root  " \
                                  "privileges to attach iSCSI devices.\n"
                            ans = False
                        else:
                            ans = ask_yes_no("Would you like to retry "
                                             "attaching this device?")
                        if ans:
                            retval = do_attach(oci_sess, iqn, targets)
                            if retval == 0:
                                ans = False
                                do_refresh = True
                        else:
                            ans = False
                else:
                    # authentication error
                    if _user_euid != 0:
                        print "You must run this program with root " \
                              "privileges to configure iSCSI devices.\n"
                        ans = False
                    else:
                        ans = ask_yes_no("Would you like to configure this "
                                         "device?")
                    if ans:
                        retval = 1
                        if USE_OCI_SDK:
                            # try and get the user and password from the API
                            retval = do_attach(oci_sess, iqn, targets,
                                               None, None)
                        else:
                            (user, passwd) = get_chap_secret(iqn)
                            if user is not None:
                                retval = do_attach(oci_sess, iqn, targets,
                                                   user, passwd)
                        if retval == 0:
                            print "Device configured automatically."
                            do_refresh = True
                        else:
                            myocid = get_instance_ocid()
                            while ans:
                                print "To find the CHAP username and " \
                                      "password for this device, go to"
                                print "https://console.us-phoenix-1." \
                                      "oraclecloud.com/#/a/compute/instances" \
                                      "/%s/disks?jt=listing" % \
                                      myocid
                                print "Select the Block Volume, then click " \
                                      "the \"iSCSI Commands & Information\" " \
                                      "button."
                                print "CHAP username:"******"CHAP password:"******"Attaching iSCSI device..."
                                retval = do_attach(oci_sess, iqn, targets,
                                                   user, passwd)
                                if retval != 0:
                                    ans = ask_yes_no("Would you like to try "
                                                     "again?")
                                else:
                                    ans = False
                                    do_refresh = True
        if do_refresh:
            ocid_refresh(debug=args.debug)
        if not args.interactive and auth_errors:
            print
            print "Use the -i or --interactive mode to configure " \
                  "devices that require authentication information"

    if not args.show and not attach_failed and not detached:
        print "All known devices are attached."
        print "Use the -s or --show option for details."

    return 0