def do_native_app_authentication(client_id, redirect_uri, requested_scopes=None): """ Does a Native App authentication flow and returns a dict of tokens keyed by service name. """ client = NativeAppAuthClient(client_id=client_id) # pass refresh_tokens=True to request refresh tokens client.oauth2_start_flow(requested_scopes=requested_scopes, redirect_uri=redirect_uri, refresh_tokens=True) url = client.oauth2_get_authorize_url() print('Native App Authorization URL: \n{}'.format(url)) if not is_remote_session(): webbrowser.open(url, new=1) auth_code = input('Enter the auth code: ').strip() token_response = client.oauth2_exchange_code_for_tokens(auth_code) # return a set of tokens, organized by resource server name return token_response.by_resource_server
def do_native_app_authentication(client_id, redirect_uri, requested_scopes=None): """ Does a Native App authentication flow and returns a dict of tokens keyed by service name. """ client = NativeAppAuthClient(client_id=client_id) # pass refresh_tokens=True to request refresh tokens client.oauth2_start_flow(requested_scopes=requested_scopes, redirect_uri=redirect_uri, refresh_tokens=True) url = client.oauth2_get_authorize_url() print('Native App Authorization URL:\n{}'.format(url)) if not is_remote_session(): # There was a bug in webbrowser recently that this fixes: # https://bugs.python.org/issue30392 if sys.platform == 'darwin': webbrowser.get('safari').open(url, new=1) else: webbrowser.open(url, new=1) auth_code = get_input('Enter the auth code: ').strip() token_response = client.oauth2_exchange_code_for_tokens(auth_code) # return a set of tokens, organized by resource server name return token_response.by_resource_server
def login(): tok_path = os.path.expanduser('~/.mdf_agent_tokens.json') def _read_tokfile(): tokens = {} if os.path.exists(tok_path): with open(tok_path) as f: tokens = json.load(f) return tokens def _write_tokfile(new_tokens): # We have multiple tokens in our tokens file, but on update we only # get the currently updated token, so read current and update with the # input tokens cur_tokens = _read_tokfile() for key in new_tokens: cur_tokens[key] = new_tokens[key] # deny rwx to Group and World -- don't bother storing the returned old # mask value, since we'll never restore it anyway # do this on every call to ensure that we're always consistent about it os.umask(0o077) with open(tok_path, 'w') as f: f.write(json.dumps(cur_tokens)) def _update_tokfile(tokens): _write_tokfile(tokens.by_resource_server['transfer.api.globus.org']) tokens = _read_tokfile() client_id = "1e162bfc-ad52-4014-8844-b82841145fc4" native_client = NativeAppAuthClient(client_id, app_name='MDF Agents') if not tokens: # and do the Native App Grant flow native_client.oauth2_start_flow( requested_scopes='urn:globus:auth:scope:transfer.api.globus.org:all', refresh_tokens=True) linkprompt = 'Please login to Globus here' print('{0}:\n{1}\n{2}\n{1}\n' .format(linkprompt, '-' * len(linkprompt), native_client.oauth2_get_authorize_url()), flush=True) auth_code = input( 'Enter the resulting Authorization Code here').strip() tkns = native_client.oauth2_exchange_code_for_tokens(auth_code) tokens = tkns.by_resource_server['transfer.api.globus.org'] _write_tokfile(tokens) transfer_tokens = tokens transfer_authorizer = RefreshTokenAuthorizer( transfer_tokens['refresh_token'], native_client, transfer_tokens['access_token'], transfer_tokens['expires_at_seconds'], on_refresh=_update_tokfile) transfer_client = TransferClient(authorizer=transfer_authorizer) return transfer_client
def register_agent(self): """ Manage the login with Globus and register this agent with the cloud service under this user's name. If it is a new user they will have account created for them by the service. """ scopes = ("urn:globus:auth:scope:transfer.api.globus.org:all " "urn:globus:auth:scope:auth.globus.org:view_identities " "openid email profile") redirect_uri = 'https://auth.globus.org/v2/web/auth-code' client = NativeAppAuthClient(client_id=self.client_id) client.oauth2_start_flow(requested_scopes=scopes, redirect_uri=redirect_uri, refresh_tokens=True) url = client.oauth2_get_authorize_url() print('Globus Authorization URL: \n{}'.format(url)) auth_code = input('Enter the auth code: ').strip() token_response = client.oauth2_exchange_code_for_tokens(auth_code) id_data = token_response.decode_id_token(client) user_email = id_data.get('preferred_username', '') transfer_tokens = token_response.by_resource_server[ 'transfer.api.globus.org'] print('Authenticated as: %s' % user_email) # Get a user friendly name for this agent agent_name = input( 'Enter a name for this agent (e.g. laptop): ').strip() payload = { "access_token": transfer_tokens['access_token'], "username": user_email, "agent_id": self.endpoint_id, "refresh_token": transfer_tokens['refresh_token'], "expires_at_seconds": transfer_tokens['expires_at_seconds'], "agent_name": agent_name } # register this data with the service r = requests.post(self.agent_path, json=payload) logger.info("Response: %s %s" % (r.status_code, r.reason)) # Check it was successfully registered, otherwise try again # Note: this returns 500 at the moment as I haven't configured # a response integration with SNS. if r.status_code == requests.codes.ok or r.status_code == 500: logger.info("Successfully registered agent.")
class OAuth2(object): """Base class for OAuth2 model """ def __init__(self): """Initiate an OAuth2() object. Initiate OAuth2 flow with Globus credentaials to obtain access tokens. Refresh the tokens automatically so another login is not required. Examples -------- Create an OAuth2 object: >>> from archeion.models import OAuth2 >>> authorizer = OAuth2() """ self.client = NativeAppAuthClient(CLIENT_ID) self.client.oauth2_start_flow(refresh_tokens=True) logger.info("Opening browser window for Globus Authentication") webbrowser.open_new(self.client.oauth2_get_authorize_url()) get_input = getattr(__builtins__, "raw_input", input) auth_code = get_input( "Please enter the code you get after login here: " ).strip() logger.debug("User has input authentication code") token_response = self.client.oauth2_exchange_code_for_tokens(auth_code) self.access_token = token_response.by_resource_server["auth.globus.org"][ "access_token" ] transfer_response = token_response.by_resource_server["transfer.api.globus.org"] self.transfer_token = transfer_response["access_token"] self.transfer_refresh_token = transfer_response["refresh_token"] self.transfer_expiry_seconds = transfer_response["expires_at_seconds"] authorizer = RefreshTokenAuthorizer( self.transfer_refresh_token, self.client, access_token=self.transfer_token, expires_at=self.transfer_expiry_seconds, ) self.transfer_client = TransferClient( AccessTokenAuthorizer(self.transfer_token) ) self.authorisation_client = AuthClient(authorizer=authorizer)
def _do_login_for_scopes(native_client: NativeAppAuthClient, scopes: List[str]) -> OAuthTokenResponse: label = CLIENT_NAME host = platform.node() if host: label = label + f" on {host}" native_client.oauth2_start_flow( requested_scopes=scopes, refresh_tokens=True, prefill_named_grant=label, ) linkprompt = "Please log into Globus here" safeprint("{0}:\n{1}\n{2}\n{1}\n".format( linkprompt, "-" * len(linkprompt), native_client.oauth2_get_authorize_url())) auth_code = click.prompt( "Enter the resulting Authorization Code here").strip() return native_client.oauth2_exchange_code_for_tokens(auth_code)
def do_native_app_authentication(client_id=config['CLIENT_ID'], redirect_uri=config['REDIRECT_URI'], requested_scopes=config['SCOPES']): """ Does a Native App authentication flow and returns a dict of tokens keyed by service name. """ client = NativeAppAuthClient(client_id=client_id) client.oauth2_start_flow(requested_scopes=config['SCOPES'], redirect_uri=redirect_uri) url = client.oauth2_get_authorize_url() server = start_local_server(listen=config['SERVER_ADDRESS']) if not is_remote_session(): webbrowser.open(url, new=1) auth_code = server.wait_for_code() token_response = client.oauth2_exchange_code_for_tokens(auth_code) server.shutdown() # return a set of tokens, organized by resource server name return token_response.by_resource_server
class GlobusStorageManager: # https://globus-sdk-python.readthedocs.io/en/stable/clients/transfer/ app_id = 'b2fe5703-edb0-4f7f-80a6-2147c8ae35f0' # map transfer app id class GlobusQueue: ''' placeholder for globus async helpers ''' pass def __init__(self): self.auth_client = NativeAppAuthClient(self.app_id) self.auth_client.oauth2_start_flow(refresh_tokens=True) self.xfer_client = None custom = dj.config.get('custom', None) if custom and 'globus.token' in custom: self.refresh() else: self.login() # authentication methods def login(self): ''' fetch refresh token, store in dj.config['globus.token'] ''' auth_client = self.auth_client print('Please login via: {}'.format( auth_client.oauth2_get_authorize_url())) code = input('and enter code:').strip() tokens = auth_client.oauth2_exchange_code_for_tokens(code) xfer_auth_cfg = tokens.by_resource_server['transfer.api.globus.org'] xfer_rt = xfer_auth_cfg['refresh_token'] xfer_at = xfer_auth_cfg['access_token'] xfer_exp = xfer_auth_cfg['expires_at_seconds'] xfer_auth = RefreshTokenAuthorizer( xfer_rt, auth_client, access_token=xfer_at, expires_at=xfer_exp) self.xfer_client = TransferClient(authorizer=xfer_auth) custom = dj.config.get('custom', {}) custom['globus.token'] = xfer_rt dj.config['custom'] = custom def refresh(self): ''' use refresh token to refresh access token ''' auth_client = self.auth_client xfer_auth = RefreshTokenAuthorizer( dj.config['custom']['globus.token'], auth_client, access_token=None, expires_at=None) self.xfer_client = TransferClient(authorizer=xfer_auth) # endpoint managment / utility methods @classmethod def ep_parts(cls, endpoint_path): # split endpoint:/path to endpoint, path epsplit = endpoint_path.split(':') return epsplit[0], ':'.join(epsplit[1:]) def activate_endpoint(self, endpoint): ''' activate an endpoint ''' tc = self.xfer_client r = tc.endpoint_autoactivate(endpoint, if_expires_in=3600) log.debug('activate_endpoint() code: {}'.format(r['code'])) if r['code'] == 'AutoActivationFailed': print('Endpoint({}) Not Active! Error! Source message: {}' .format(endpoint, r['message'])) raise Exception('globus endpoint activation failure') knownok = any(('AutoActivated' in r['code'], 'AlreadyActivated' in r['code'])) if not knownok: log.debug('activate_endpoint(): not knownok response') def _wait(self, task, timeout=10, polling_interval=10): ''' tranfer client common wait wrapper ''' return self.xfer_client.task_wait(task, timeout, polling_interval) def _tasks(self): ''' >>> tl = tc.task_list(num_results=25, filter="type:TRANSFER,DELETE") >>> _ = [print(t["task_id"], t["type"], t["status"]) for t in tl] ''' pass def _task_info(self): ''' >>> for event in tc.task_event_list(task_id): >>> print("Event on Task({}) at {}:\n{}".format( >>> task_id, event["time"], event["description"]) or get_task ''' pass # transfer methods def ls(self, endpoint_path): ''' returns: { "DATA": [ { "DATA_TYPE": "file", "group": "staff", "last_modified": "2018-05-22 18:49:19+00:00", "link_group": null, "link_last_modified": null, "link_size": null, "link_target": null, "link_user": null, "name": "map", "permissions": "0755", "size": 102, "type": "dir", "user": "******" }, ], "DATA_TYPE": "file_list", "absolute_path": null, "endpoint": "aa4e5f9c-05f3-11e8-a6ad-0a448319c2f8", "length": 2, "path": "/~/Globus/", "rename_supported": true, "symlink_supported": false, "total": 2 } ''' ep, path = self.ep_parts(endpoint_path) return self.xfer_client.operation_ls(ep, path=path) def mkdir(self, ep_path): ''' create a directory at ep_path ''' ep, path = self.ep_parts(ep_path) return self.xfer_client.operation_mkdir(ep, path=path) def rmdir(self, ep_path, recursive=False): ''' remove a directory at ep_path ''' tc = self.xfer_client ep, path = self.ep_parts(ep_path) ddata = DeleteData(tc, ep, recursive=recursive) ddata.add_item(path) task_id = tc.submit_delete(ddata)['task_id'] return self._wait(task_id) def cp(self, src_ep_path, dst_ep_path, recursive=False): ''' copy file/path todo: support label, sync_level, etc? sync_level: ["exists", "size", "mtime", "checksum"] ''' tc = self.xfer_client sep, spath = self.ep_parts(src_ep_path) dep, dpath = self.ep_parts(dst_ep_path) td = TransferData(tc, sep, dep) td.add_item(spath, dpath, recursive=recursive) task_id = tc.submit_transfer(td)['task_id'] return self._wait(task_id) def rename(self, src_ep_path, dst_ep_path): ''' rename a file/path ''' tc = self.xfer_client sep, spath = self.ep_parts(src_ep_path) dep, dpath = self.ep_parts(dst_ep_path) if sep != dep: raise Exception('rename between two different endpoints') return tc.operation_rename(sep, spath, dpath)
#!/usr/bin/env python from globus_sdk import NativeAppAuthClient CLIENT_ID = "d0f1d9b0-bd81-4108-be74-ea981664453a" SCOPES = ("openid profile email " "urn:globus:auth:scope:transfer.api.globus.org:all") get_input = getattr(__builtins__, 'raw_input', input) client = NativeAppAuthClient(client_id=CLIENT_ID) client.oauth2_start_flow(requested_scopes=SCOPES, refresh_tokens=True) url = client.oauth2_get_authorize_url() print("Native App Authorization URL: \n{}".format(url)) auth_code = get_input("Enter the auth code: ").strip() token_res = client.oauth2_exchange_code_for_tokens(auth_code) tokens = token_res.by_resource_server transfer_token = tokens["transfer.api.globus.org"]["refresh_token"] auth_token = tokens["auth.globus.org"]["refresh_token"] id_token = token_res["id_token"] access_token = token_res["access_token"] print("Transfer Refresh Token: {}".format(transfer_token)) print("Auth Refresh Token : {}".format(auth_token)) print("Openid id_token : {}".format(id_token)) print("Access Token : {}".format(access_token))
class NativeClient(object): """ The Native Client serves as another small layer on top of the Globus SDK to automatically handle token storage and provide a customizable Local Server. It can be used both by simple scripts to simplify the auth flow, or by full command line clients that may extend various pieces and tailor them to its own needs. """ TOKEN_STORAGE_ATTRS = {'write_tokens', 'read_tokens', 'clear_tokens'} def __init__(self, token_storage=MultiClientTokenStorage(), local_server_code_handler=LocalServerCodeHandler(), secondary_code_handler=InputCodeHandler(), default_scopes=None, *args, **kwargs): self.client = NativeAppAuthClient(*args, **kwargs) self.token_storage = token_storage if token_storage is not None: self.verify_token_storage(self.token_storage) self.app_name = kwargs.get('app_name') or 'My App' self.local_server_code_handler = local_server_code_handler self.local_server_code_handler.set_app_name(self.app_name) self.secondary_code_handler = secondary_code_handler if isinstance(self.token_storage, MultiClientTokenStorage): self.token_storage.set_client_id(kwargs.get('client_id')) self.default_scopes = default_scopes def login(self, no_local_server=False, no_browser=False, requested_scopes=(), refresh_tokens=None, prefill_named_grant=None, additional_params=None, force=False): """ Do a Native App Auth Flow to get tokens for requested scopes. This first attempts to load tokens and will simply return those if they are valid, and will automatically attempt to save tokens on login success (token_storage must be set for automatic load/save functionality). :param no_local_server: Don't use the local server. This may be because of permissions issues of standing up a server on the clients machine. :param no_browser: Don't automatically open a browser, and instead instruct the user to manually follow the URL to login. This is useful on remote servers which don't have native browsers for clients to use. :param requested_scopes: Globus Scopes to request on the users behalf. :param refresh_tokens: Use refresh tokens to extend login time :param prefill_named_grant: Named Grant to use on Consent Page :param additional_params: Additional Params to supply, such as for using Globus Sessions :param force: Force a login flow, even if loaded tokens are valid. :return: """ if force is False: try: return self.load_tokens(requested_scopes=requested_scopes) except (LoadError, Exception): pass grant_name = prefill_named_grant or '{} Login'.format(self.app_name) code_handler = (self.secondary_code_handler if no_local_server else self.local_server_code_handler) with code_handler.start(): self.client.oauth2_start_flow( requested_scopes=requested_scopes or self.default_scopes, refresh_tokens=refresh_tokens, prefill_named_grant=grant_name, redirect_uri=code_handler.get_redirect_uri()) auth_url = self.client.oauth2_get_authorize_url( additional_params=additional_params) auth_code = code_handler.authenticate(url=auth_url, no_browser=no_browser) token_response = self.client.oauth2_exchange_code_for_tokens(auth_code) try: self.save_tokens(token_response.by_resource_server) except LoadError: pass return token_response.by_resource_server def verify_token_storage(self, obj): for attr in self.TOKEN_STORAGE_ATTRS: if getattr(obj, attr, None) is None: raise AttributeError('token_storage requires object "{}" to ' 'have the {} attribute'.format(obj, attr)) def save_tokens(self, tokens): """ Save tokens if token_storage is set. Typically this is called automatically in a successful login(). :param tokens: globus_sdk.auth.token_response.OAuthTokenResponse. :return: None """ if self.token_storage is not None: return self.token_storage.write_tokens(tokens) raise LoadError('No token_storage set on client.') def _load_raw_tokens(self): """ Loads tokens without checking them :return: tokens by resource server, or an exception if that fails """ if self.token_storage is not None: return self.token_storage.read_tokens() raise LoadError('No token_storage set on client.') def load_tokens(self, requested_scopes=None): """ Load tokens from the set token_storage object if one exists. :param requested_scopes: Check that the loaded scopes match these requested scopes. Raises ScopesMismatch if there is a discrepancy. :return: Loaded tokens, or a LoadError if loading fails. """ tokens = self._load_raw_tokens() if not tokens: raise LoadError('No Tokens loaded') if requested_scopes not in [None, ()]: check_scopes(tokens, requested_scopes) try: check_expired(tokens) except TokensExpired as te: expired = {rs: tokens[rs] for rs in te.resource_servers} if not self._refreshable(expired): raise tokens.update(self.refresh_tokens(expired)) self.save_tokens(tokens) return tokens def _refreshable(self, tokens): return all([bool(ts['refresh_token']) for ts in tokens.values()]) def refresh_tokens(self, tokens): if not self._refreshable(tokens): raise TokensExpired('No Refresh Token, cannot refresh tokens: ', resource_servers=tokens.keys()) for rs, token_dict in tokens.items(): authorizer = RefreshTokenAuthorizer( token_dict['refresh_token'], self.client, access_token=token_dict['access_token'], expires_at=token_dict['expires_at_seconds'], ) authorizer.check_expiration_time() token_dict['access_token'] = authorizer.access_token token_dict['expires_at_seconds'] = authorizer.expires_at return tokens def get_authorizers(self): authorizers = {} for resource_server, token_dict in self.load_tokens().items(): if token_dict.get('refresh_token') is not None: authorizers[resource_server] = RefreshTokenAuthorizer( token_dict['refresh_token'], self.client, access_token=token_dict['access_token'], expires_at=token_dict['expires_at_seconds'], on_refresh=self.on_refresh, ) else: authorizers[resource_server] = AccessTokenAuthorizer( token_dict['access_token']) return authorizers def on_refresh(self, token_response): loaded_tokens = self._load_raw_tokens() loaded_tokens.update(token_response.by_resource_server) self.save_tokens(loaded_tokens) def logout(self): """ Revoke saved tokens and clear them from storage """ self.revoke_token_set(self._load_raw_tokens()) self.token_storage.clear_tokens() def revoke_token_set(self, tokens): for rs, tok_set in tokens.items(): self.client.oauth2_revoke_token(tok_set.get('access_token')) self.client.oauth2_revoke_token(tok_set.get('refresh_token'))
def initiate_connection(self): """ Initiate the connection """ tokens = None try: # if we already have tokens, load and use them tokens = self.load_tokens_from_file() except: pass if not tokens: # if we need to get tokens, start the Native App authentication process client = NativeAppAuthClient( client_id=self.CLIENT_ID) #self.config['client_id']) # pass refresh_tokens=True to request refresh tokens client.oauth2_start_flow( requested_scopes=self. SCOPES, #self.config['requested_scopes'], redirect_uri=self.REDIRECT_URI, #self.config['redirect_uri'], refresh_tokens=True) url = client.oauth2_get_authorize_url() print 'Native App Authorization URL: \n{}'.format(url) auth_code = raw_input('Enter the auth code: ').strip() token_response = client.oauth2_exchange_code_for_tokens(auth_code) # return a set of tokens, organized by resource server name tokens = token_response.by_resource_server try: self.save_tokens_to_file(tokens) except: pass transfer_tokens = tokens['transfer.api.globus.org'] auth_client = NativeAppAuthClient(client_id=self.config['client_id']) authorizer = RefreshTokenAuthorizer( transfer_tokens['refresh_token'], auth_client, #access_token=transfer_tokens['access_token'], #expires_at=transfer_tokens['expires_at_seconds'], on_refresh=self.update_tokens_file_on_refresh) self.client = TransferClient(authorizer=authorizer) # print out a directory listing from an endpoint try: #print 'ACTIVATE' #print 'DEST',self.config['dest_ep'] self.client.endpoint_autoactivate(self.config['dest_ep']) ac = self.client.endpoint_get_activation_requirements( self.config['dest_ep']) #print ac self.client.endpoint_autoactivate(self.config['src_ep']) ac2 = self.client.endpoint_get_activation_requirements( self.config['src_ep']) #print ac2 except GlobusAPIError as ex: self.logger.error('Error in endpoint activation %s', str(ex)) if ex.http_status == 401: sys.exit('Refresh token has expired. ' 'Please delete refresh-tokens.json and try again.') else: raise ex
class Transfer: ''' Modified Transfer, add an option to pass refresh token to avoid the web login ''' def __init__(self, src_endpoint_name, dst_endpoint_name, transfer_rt=None, log_lv=logging.INFO): log_format = '%(asctime)-15s %(levelname)s:\t class:%(name)s %(message)s' logging.basicConfig(format=log_format) self.logger = logging.getLogger(self.__class__.__name__) self.logger.setLevel(log_lv) self.logger.debug('CLIENT_ID: {0}'.format(CLIENT_ID)) self.client = NativeAppAuthClient(CLIENT_ID) self.client.oauth2_start_flow(refresh_tokens=True) if transfer_rt is not None: self.authorizer = RefreshTokenAuthorizer(transfer_rt, self.client) else: authorize_url = self.client.oauth2_get_authorize_url() print('Please go to this URL and login: {0}'.format(authorize_url)) get_input = getattr(__builtins__, 'raw_input', input) auth_code = get_input( 'Please enter the code you get after login here: ').strip() token_response = self.client.oauth2_exchange_code_for_tokens( auth_code) self.globus_auth_data = token_response.by_resource_server[ 'auth.globus.org'] self.globus_transfer_data = token_response.by_resource_server[ 'transfer.api.globus.org'] auth_token = self.globus_auth_data['access_token'] transfer_token = self.globus_transfer_data['access_token'] transfer_rt = self.globus_transfer_data['refresh_token'] transfer_at = self.globus_transfer_data['access_token'] expires_at_s = self.globus_transfer_data['expires_at_seconds'] self.authorizer = RefreshTokenAuthorizer(transfer_rt, self.client, access_token=transfer_at, expires_at=expires_at_s) self.transferClient = TransferClient(authorizer=self.authorizer) self.src_endpoint = None self.dst_endpoint = None for ep in self.transferClient.endpoint_search( filter_scope="shared-with-me"): if ep["display_name"] == src_endpoint_name: self.src_endpoint = ep self.logger.info('Source endpoint: [{0}] {1}'.format( self.src_endpoint['id'], self.src_endpoint['display_name'])) if self.src_endpoint is None: self.logger.error( 'No endpoint shared with you with name: {0}'.format( src_endpoint_name)) raise LookupError for ep in self.transferClient.endpoint_search( filter_scope="my-endpoints"): if ep['display_name'] == dst_endpoint_name: self.dst_endpoint = ep self.logger.info('Destination endpoint: [{0}] {1}'.format( self.dst_endpoint['id'], self.dst_endpoint['display_name'])) if self.dst_endpoint is None: self.logger.error('You don\'t have endpoint named: {0}'.format( dst_endpoint_name)) raise LookupError def transfer_dir(self, src_dir, dst_dir): transfer_data = TransferData(self.transferClient, self.src_endpoint['id'], self.dst_endpoint['id']) transfer_data.add_item(src_dir, dst_dir, recursive=True) result = self.transferClient.submit_transfer(transfer_data) self.logger.info('task [{0}] {1}'.format(result['task_id'], result['code'])) return result def transfer_file(self, src_file, dst_file): transfer_data = TransferData(self.transferClient, self.src_endpoint['id'], self.dst_endpoint['id']) transfer_data.add_item(src_file, dst_file) result = self.transferClient.submit_transfer(transfer_data) self.logger.info('task_id [{0}] {1}'.format(result['task_id'], result['code'])) return result def ls_src_dir(self, path, ls_filter=''): # using iteration to get every entry from result # an entry contain two keys: 'name' and 'type' # type define the entry is a file or folder result = self.transferClient.operation_ls(self.src_endpoint['id'], path=path, filter=ls_filter) for entry in result: self.logger.debug('name: {0}\ttype: {1}'.format( entry["name"], entry["type"])) return result def task_list(self, num_results=10): result = self.transferClient.task_list(num_results=num_results) for task in result: self.logger.debug('task_id: [{0}]\t status: {1}'.format( task['task_id'], task['status'])) result = self.transferClient.task_list(num_results=num_results) return result def get_task(self, task_id): return self.transferClient.get_task(task_id)