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