def test_write_cache(self): """ Test cache.write_cache(). Returns ------- No return value. """ ts0 = write_cache(cache_fname=self.file3, cache_content={'hello': 'world'}) self.assertNotEqual(ts0, None, "New cache write return None as timestamp") ts = get_timestamp(self.file3) self.assertEqual( ts0, ts, "timestamp returned from get_timestamp differ form " "one returned by write_cache") self.assertEqual(load_cache(self.file3), (ts, { 'hello': 'world' }), 'Unexpected return values from load_cache()') self.assertFalse( write_cache(cache_fname='/proc/foo1', cache_content={})) self.assertFalse( write_cache(cache_fname='/proc/foo1', fallback_fname='/proc/foo3', cache_content={})) self.assertTrue( write_cache(cache_fname='/proc/foo1', fallback_fname=self.file3, cache_content={'hello': 'again'})) ts = get_timestamp(self.file3) self.assertEqual(load_cache(self.file3), (ts, {'hello': 'again'}))
def save_chap_secret(iqn, user, password): """ Save the login information for the given iqn in the chap secrets file. Parameters ---------- iqn: str The iSCSI qualified name. user: str The iscsiadm username. password: str The iscsiadm password. Returns ------- No return value. """ _, chap_passwords = \ load_cache(oci_utils.__chap_password_file) if chap_passwords is None: chap_passwords = {} chap_passwords[iqn] = (user, password) write_cache(cache_content=chap_passwords, cache_fname=oci_utils.__chap_password_file, mode=0o600)
def iscsi_func(context, func_logger): """ OCID thread function for discovering and attaching/detaching block volumes; context must include 'max_volumes' and 'auto_detach'. Parameters ---------- context: dict The thread context. func_logger: logger Returns ------- dict The new context. """ if 'oci_sess' not in context: oci_sess = None try: oci_sess = oci_utils.oci_api.OCISession() except Exception as e: func_logger.debug('Failed to get a session: %s' % str(e)) max_volumes = 8 if 'max_volumes' in context: max_volumes = int(context['max_volumes']) auto_detach = True if 'auto_detach' in context: auto_detach = context['auto_detach'] # the number of iterations to wait before detaching an offline volume detach_retry = 5 if 'detach_retry' in context: detach_retry = int(context['detach_retry']) if max_volumes > _MAX_VOLUMES_LIMIT: func_logger.warn("Your configured max_volumes(%s) is over the limit(%s)\n" % (max_volumes, _MAX_VOLUMES_LIMIT)) max_volumes = _MAX_VOLUMES_LIMIT context = {'ignore_file_ts': 0, 'ignore_iqns': [], 'attach_failed': {}, 'chap_pw_ts': 0, 'chap_pws': {}, 'oci_sess': oci_sess, 'max_volumes': max_volumes, 'offline_vols': {}, 'auto_detach': auto_detach, 'detach_retry': detach_retry, } # devices currently attached session_devs = oci_utils.iscsiadm.session() # Load the saved passwords chap_passwords = context['chap_pws'] if context['chap_pw_ts'] == 0 \ or get_timestamp(oci_utils.__chap_password_file) > context['chap_pw_ts']: # the password file has changed or was never loaded context['chap_pw_ts'], chap_passwords = load_cache(oci_utils.__chap_password_file) if chap_passwords is None: chap_passwords = {} # save for the next iteration context['chap_pws'] = chap_passwords # volumes that are offline in this iteration new_offline_vols = {} all_iqns = {} # ------------------------------------------------------------------------------------- # possible change for LINUX-11440; comment out the in-between # verify if user has authorisation to list volumes; if not, scan for new volumes. # volumes = None # if context['oci_sess'] is not None: # try: # # # # get a list of volumes attached to the instance # instance = context['oci_sess'].this_instance() # if instance is None: # func_logger.debug('Cannot get current instance.') # else: # volumes = instance.all_volumes() # except Exception as e: # func_logger.debug('User is not authorized to list all volumes.') # ------------------------------------------------------------------------------------- # # volumes connected to this instance inst_volumes = [] if context['oci_sess'] is not None: # # get a list of volumes attached to the instance instance = context['oci_sess'].this_instance() if instance is None: func_logger.debug('Cannot get current instance.') else: volumes = instance.all_volumes() for v in volumes: vol = {'iqn': v.get_iqn(), 'ipaddr': v.get_portal_ip(), 'user': v.get_user(), 'password': v.get_password()} inst_volumes.append(vol) if v.get_portal_ip() in all_iqns: all_iqns[v.get_portal_ip()].append(v.get_iqn()) else: all_iqns[v.get_portal_ip()] = [v.get_iqn()] func_logger.debug('All volumes: %s', all_iqns) # ------------------------------------------------------------------------------------- # # possible change for LINUX-11440; comment out the above # if bool(volumes): # for v in volumes: # vol = {'iqn': v.get_iqn(), # 'ipaddr': v.get_portal_ip(), # 'user': v.get_user(), # 'password': v.get_password()} # inst_volumes.append(vol) # if v.get_portal_ip() in all_iqns: # all_iqns[v.get_portal_ip()].append(v.get_iqn()) # else: # all_iqns[v.get_portal_ip()] = [v.get_iqn()] # func_logger.debug('All volumes: %s', all_iqns) # # ------------------------------------------------------------------------------------- else: # # fall back to scanning func_logger.debug('Scan for volumes.') for r in range(context['max_volumes'] + 1): ipaddr = "169.254.2.%d" % (r + 1) iqns = oci_utils.iscsiadm.discovery(ipaddr) all_iqns[ipaddr] = iqns for iqn in iqns: vol = {'iqn': iqn, 'ipaddr': ipaddr, 'user': None, 'password': None} # look for a saved password if iqn in chap_passwords: vol['user'] = chap_passwords[iqn][0] vol['password'] = chap_passwords[iqn][1] inst_volumes.append(vol) func_logger.debug('Scanned volumes: %s', inst_volumes) # # Load the list of volumes that were detached using oci-iscsi-config. # ocid shouldn't attach these automatically. ignore_iqns = context['ignore_iqns'] if context['ignore_file_ts'] == 0 or get_timestamp(oci_utils.__ignore_file) > context['ignore_file_ts']: # # the list of detached volumes changed since last reading the file context['ignore_file_ts'], ignore_iqns = load_cache(oci_utils.__ignore_file) if ignore_iqns is None: ignore_iqns = [] # # save for next iteration context['ignore_iqns'] = ignore_iqns # # volumes that failed to attach in an earlier iteration attach_failed = context['attach_failed'] # # do we need to cache files? cache_changed = False ign_changed = False chap_changed = False # # if inst_volumes is empty, clean iscsiadm-cache to. if not bool(inst_volumes): all_iqns = {} write_cache(cache_content=[all_iqns, attach_failed], cache_fname=oci_utils.iscsiadm.ISCSIADM_CACHE) # # check if all discovered iscsi devices are configured and attached for vol in inst_volumes: func_logger.debug('iqn: %s', vol['iqn']) if vol['iqn'] in ignore_iqns: # a device that was manually detached, so don't # re-attach it automatically continue if vol['iqn'] not in session_devs: if vol['iqn'] in attach_failed: # previous attempt to attach failed, ignore continue cache_changed = True # configure and attach the device __ocid_logger.info("Attaching iscsi device: %s:%s (%s)", vol['ipaddr'], "3260", vol['iqn']) if vol['user'] is not None: attach_result = oci_utils.iscsiadm.attach(vol['ipaddr'], 3260, vol['iqn'], vol['user'], vol['password'], auto_startup=True) if vol['iqn'] not in chap_passwords: chap_passwords[vol['iqn']] = (vol['user'], vol['password']) chap_changed = True else: attach_result = oci_utils.iscsiadm.attach(vol['ipaddr'], 3260, vol['iqn'], auto_startup=True) if attach_result != 0: func_logger.info("Failed to attach device: %s" % oci_utils.iscsiadm.error_message_from_code(attach_result)) attach_failed[vol['iqn']] = attach_result cache_changed = True else: # # iqn is in session_devs but not in iscsiadm cache write_cache(cache_content=[all_iqns, attach_failed], cache_fname=oci_utils.iscsiadm.ISCSIADM_CACHE) # look for previously failed volumes that are now in the session # (e.g. the user supplied the password using oci-iscsi-config) for iqn in list(attach_failed.keys()): if iqn in session_devs: del attach_failed[iqn] cache_changed = True detach_retry = 5 if 'detach_retry' in context: detach_retry = int(context['detach_retry']) # look for disconnected devices in the current session # these devices were disconnected from the instance in the console, # we now have to detach them from at the OS level for iqn in session_devs: # # ignore the boot device if iqn.endswith('boot:uefi'): continue if 'state' not in session_devs[iqn]: continue if session_devs[iqn]['state'] in ['blocked', 'transport-offline']: func_logger.debug("Checking iqn %s (state %s)\n" % (iqn, session_devs[iqn]['state'])) # # is the iqn discoverable at the portal? if iqn not in inst_volumes: # Not found by iscsiadm discovery. # To allow time for the volume to recover, wait for detach_retry # iterations where the volume was offline before detaching it if iqn not in context['offline_vols']: func_logger.info("iSCSI volume appears to be offline: %s" % iqn) new_offline_vols[iqn] = 1 continue if context['offline_vols'][iqn] < detach_retry: new_offline_vols[iqn] = context['offline_vols'][iqn] + 1 func_logger.info("iSCSI volume still offline (%d): %s" % (new_offline_vols[iqn], iqn)) continue if not context['auto_detach']: func_logger.info("Volume still offline, but iSCSI auto_detach disabled: %s" % iqn) new_offline_vols[iqn] = detach_retry + 1 continue cache_changed = True ipaddr = session_devs[iqn]['persistent_portal_ip'] func_logger.info("Detaching iSCSI device: %s:%s (%s)" % (ipaddr, "3260", iqn)) oci_utils.iscsiadm.detach(ipaddr, 3260, iqn) # # delete from list of previously offline volumes so it # doesn't get reported as 'now online' del context['offline_vols'][iqn] # # device is gone, remove from "ignore" list if iqn in ignore_iqns: ignore_iqns.remove(iqn) ign_changed = True # # remove from attach_failed list if present if iqn in attach_failed: del attach_failed[iqn] cache_changed = True # # look for devices that were previously offline but now back online # (just for printing a message that it's now online) for iqn in context['offline_vols']: if iqn not in new_offline_vols: func_logger.info("iSCSI volume now online: %s" % iqn) context['offline_vols'] = new_offline_vols # # check if the devices that were previously manually detached are still # connected to the instance inst_iqns = [vol['iqn'] for vol in inst_volumes] for iqn in ignore_iqns: # if iqn not in inst_iqns: # GT if iqn in inst_iqns: func_logger.debug("Removing iqn %s from ignore list" % iqn) ignore_iqns.remove(iqn) ign_changed = True # rewrite changed cache files if ign_changed: context['ignore_file_ts'] = \ write_cache(cache_content=ignore_iqns, cache_fname=oci_utils.__ignore_file) if chap_changed: context['chap_pw_ts'] = \ write_cache(cache_content=chap_passwords, cache_fname=oci_utils.__chap_password_file, mode=0o600) if cache_changed or not os.path.exists(oci_utils.iscsiadm.ISCSIADM_CACHE): write_cache(cache_content=[all_iqns, attach_failed], cache_fname=oci_utils.iscsiadm.ISCSIADM_CACHE) else: try: os.utime(oci_utils.iscsiadm.ISCSIADM_CACHE, None) except Exception as e: func_logger.warn("Failed to update cache timestamp: %s" % e) return context
def main(): """ Main. Returns ------- int Return value of the operation, if any. 0 otherwise. """ parser = get_args_parser() args = parser.parse_args() if args.command is None: # default to 'sync' command args.command = "sync" if args.command == 'usage': parser.print_help() sys.exit(0) oci_sess = None try: oci_sess = oci_utils.oci_api.OCISession() except Exception as e: _logger.debug('Cannot get OCI session: %s', str(e)) system_disks = lsblk.list() iscsiadm_session = iscsiadm.session() if args.command == 'show': display_current_devices(oci_sess, iscsiadm_session, system_disks) if args.compartments: api_display_available_block_volumes(oci_sess, args.compartments, args.all) else: api_display_available_block_volumes(oci_sess, None, args.all) return 0 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)", 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: _logger.debug('updating the cache') # run ocid once, to update the cache ocid_refresh(wait=True) # 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 detached_volume_iqns = load_cache(__ignore_file)[1] if detached_volume_iqns is None: detached_volume_iqns = [] if args.command == 'sync' and not detached_volume_iqns and not attach_failed: # nothing to do, stop here print("All known devices are attached.") print("Use the -s or --show option for details.") # starting from here, nothing works if we are not root _user_euid = os.geteuid() if _user_euid != 0: _logger.error("You must run this program with root privileges") return 1 if args.command == 'sync': # we still have volume not attached, process them. retval = 0 _did_something = False if detached_volume_iqns: print() print("Detached devices:") for iqn in detached_volume_iqns: display_detached_iscsi_device(iqn, targets) if args.apply or args.interactive: if args.yes: ans = True else: ans = ask_yes_no( "Would you like to attach this device?") if ans: try: _do_iscsiadm_attach(oci_sess, iqn, targets) _did_something = True except Exception as e: _logger.error('[%s] attachment failed: %s', iqn, str(e)) retval = 1 if attach_failed: _logger.info("Devices that could not be attached automatically:") for iqn in list(attach_failed.keys()): display_detached_iscsi_device(iqn, targets, attach_failed) _attach_user_name = None _attach_user_passwd = None _give_it_a_try = False if args.apply or args.interactive: if attach_failed[iqn] != 24: # not authentication error if args.yes or ask_yes_no( "Would you like to retry attaching this device?" ): _give_it_a_try = True else: # authentication error if args.yes or ask_yes_no( "Would you like to configure this device?"): _give_it_a_try = True if oci_sess is not None: oci_vols = oci_sess.find_volumes(iqn=iqn) if len(oci_vols) != 1: _logger.error('volume [%s] not found', iqn) _give_it_a_try = False _attach_user_name = oci_vols[0].get_user() _attach_user_passwd = oci_vols[0].get_password( ) else: (_attach_user_name, _attach_user_passwd) = get_chap_secret(iqn) if _attach_user_name is None: _logger.error( 'Cannot retreive chap credentials') _give_it_a_try = False if _give_it_a_try: try: _do_iscsiadm_attach(iqn, targets, _attach_user_name, _attach_user_passwd) _did_something = True except Exception as e: _logger.error( "Failed to configure device automatically: %s", str(e)) retval = 1 if _did_something: ocid_refresh() return retval if args.command == 'create': if len(system_disks) > max_volumes: _logger.error("This instance reached the max_volumes(%s)", max_volumes) return 1 try: do_create_volume(oci_sess, size=args.size, display_name=args.volume_name, attach_it=args.attach_volume) except Exception as e: _logger.error('volume creation has failed: %s', str(e)) return 1 if args.show: display_current_devices(oci_sess, iscsiadm_session, system_disks) api_display_available_block_volumes(oci_sess) return 0 if args.command == 'destroy': # destroy command used to be for only one volume # changed the behavior to be more aligned with attach/dettach commands # i.e : taking more than one ocid and doing best effort retval = 0 if not args.yes: for ocid in args.ocids: _logger.info("volume : %s", ocid) if not ask_yes_no( "WARNING: the volume(s) will be destroyed. This is irreversible. Continue?" ): return 0 for ocid in args.ocids: try: _logger.debug('Destroying [%s]', ocid) do_destroy_volume(oci_sess, ocid) _logger.info("Volume [%s] is destroyed", ocid) except Exception as e: _logger.error('volume [%s] deletion has failed: %s', ocid, str(e)) retval = 1 if args.show: display_current_devices(oci_sess, iscsiadm_session, system_disks) api_display_available_block_volumes(oci_sess) return retval if args.command == 'detach': retval = 0 for iqn in args.iqns: if iqn in detached_volume_iqns: _logger.error("Target %s is already detached", iqn) retval = 1 continue if iqn not in iscsiadm_session or 'device' not in iscsiadm_session[ iqn]: _logger.error("Target %s not found", iqn) retval = 1 continue _logger.debug('unmounting the block volume') if not unmount_device(iscsiadm_session, iqn, system_disks): _logger.debug('Unmounting has failed') if not args.force: if not ask_yes_no( "Failed to unmount volume, Continue detaching anyway?" ): continue else: _logger.info( 'unmount failed, force option selected,continue anyway' ) try: _logger.debug('Detaching [%s]', iqn) do_detach_volume(oci_sess, iscsiadm_session, iqn) _logger.info("Volume [%s] is detached", iqn) detached_volume_iqns.append(iqn) except Exception as e: _logger.error('volume [%s] detach has failed: %s', iqn, str(e)) retval = 1 if args.show: display_current_devices(oci_sess, iscsiadm_session, system_disks) api_display_available_block_volumes(oci_sess) _logger.info("Updating detached volume cache file: %s", detached_volume_iqns) write_cache(cache_content=detached_volume_iqns, cache_fname=__ignore_file) _logger.debug('trigger ocid refresh') ocid_refresh() return retval if args.command == 'attach': if len(system_disks) > max_volumes: _logger.error( "This instance reached the maximum number of volumes attached (%s)", max_volumes) return 1 retval = 0 for iqn in args.iqns: _iqn_to_use = iqn _save_chap_cred = False if iqn in iscsiadm_session: _logger.info("Target %s is already attached.", iqn) continue if _iqn_to_use.startswith('ocid1.volume.oc'): _logger.debug('given IQN [%s] is an ocid, attaching it', _iqn_to_use) bs_volume = None try: bs_volume = _do_attach_oci_block_volume( oci_sess, _iqn_to_use) _logger.info("Volume [%s] is attached", _iqn_to_use) # user/pass coming from volume itself _attachment_username = bs_volume.get_user() _attachment_password = bs_volume.get_password() _iqn_to_use = bs_volume.get_iqn() except Exception as e: _logger.error('Failed to attach volume [%s]: %s', _iqn_to_use, str(e)) retval = 1 continue else: _logger.debug('given IQN [%s] is not an ocid', _iqn_to_use) if args.username is not None and args.password is not None: _attachment_username = args.username _attachment_password = args.password else: # user/pass not provided , asking for it (_attachment_username, _attachment_password) = get_chap_secret(iqn) _save_chap_cred = True _logger.debug('attaching [%s] to iSCSI session', _iqn_to_use) try: _do_iscsiadm_attach(_iqn_to_use, targets, user=_attachment_username, passwd=_attachment_password, iscsi_portal_ip=bs_volume.get_portal_ip()) _logger.debug('attach ok') if _iqn_to_use in detached_volume_iqns: detached_volume_iqns.remove(_iqn_to_use) except Exception as e: _logger.error("Failed to attach target %s: %s", _iqn_to_use, str(e)) _save_chap_cred = False retval = 1 continue if _save_chap_cred: _logger.debug('attachment OK: saving chap creds') save_chap_secret(_iqn_to_use, _attachment_username, _attachment_password) if args.show: display_current_devices(oci_sess, iscsiadm_session, system_disks) api_display_available_block_volumes(oci_sess) if retval == 0: _logger.info("Updating detached volume cache file: %s", detached_volume_iqns) write_cache(cache_content=detached_volume_iqns, cache_fname=__ignore_file) _logger.debug('trigger ocid refresh') ocid_refresh() return retval if not args.show and not attach_failed and not detached_volume_iqns: print("All known devices are attached.") print("Use the -s or --show option for details.") return 0
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