0

I'm using the sftp module of paramiko to transfer payloads to remote hosts. Part of the sftp.put call allows for specifying a callback method with signature func(int,int). I'm trying to put a transfer stats method into my Connection class to keep track of payload progress.

Here's the class I have currently:

class Connection:

    def __init__(self, endpoint, RSAKeyObj):
        self.displayHost = bcolors.OKGREEN + endpoint + bcolors.ENDC
        self.transport = paramiko.Transport((endpoint,4022))
        self.transport.connect(username='transit', pkey=RSAKeyObj)
        self.sftp = paramiko.SFTPClient.from_transport(self.transport)

        try:
            # initial sftp directory setup
            log.info('[{0}]: Setting up remote directories...'.format(self.displayHost))
            log.info(self.sftp.mkdir(JAIL_DIR))
        except:
            pass

    def static_vars(**kwargs):
        def decorate(func):
            for k in kwargs:
                setattr(func, k, kwargs[k])
            return func
        return decorate

    @static_vars(counter=0)
    def TransferStats(self, transferedBytes, totalBytes):
        if (transferedBytes / totalBytes) >= TransferStats.counter:
            log.info('Transferred: {}% [{}/{}]'.format(round((transferedBytes/totalBytes)*100,2), transferedBytes, totalBytes))
            TransferStats.counter += 0.025

    def Transmit(self,targetDir, payloadPath):
        displayText = 'Transferring package {}...'.format(payloadPath)
        self.TransferStats().counter=0

        log.info('[%s] ' % self.displayHost + displayText)
        log.info(self.sftp.put(payloadPath, '%s/%s' % (targetDir,payloadPath), callback=self.TransferStats()))

However when I try this, I get the following error:

ERROR - (, TypeError('TransferStats() takes exactly 3 arguments (1 given)',), )

This makes me think that the callback isn't getting recognized by paramiko when it tries to send it's (int,int) because of the self declaration. Is there a way around this?

3
  • 1
    may be you try passing in the Connection.TransferStats instead of TransferStats() Commented Aug 12, 2016 at 22:29
  • 1
    Also, i am a bit unsure of self.TransferStats().counter = 0. Commented Aug 12, 2016 at 22:30
  • counter is a global hidden as an attribute of a classmethod, reinitialized to 0 each time Transmit is called is called. I recommend refactoring this code to get rid of this global, by storing it in a dedicated object (or make it clearly a global). Commented Aug 12, 2016 at 22:31

1 Answer 1

2

Your problem is in :

    log.info(self.sftp.put(payloadPath, '%s/%s' % (targetDir,payloadPath), callback=self.TransferStats()))

Your error :

ERROR - (, TypeError('TransferStats() takes exactly 3 arguments (1 given)',), )

Is caused by calling TransferStats with no arguments (self.TransferStats() will result in 1 argument : the class (as it is a class method))

Just pass the classmethod:

    log.info(self.sftp.put(payloadPath, '%s/%s' % (targetDir,payloadPath), callback=self.TransferStats))

EDIT : You have the same problem in the following line :

self.TransferStats().counter=0

Remove the parentheses :

self.TransferStats.counter=0

Also, your counter attribute on TransferStats is a hidden a global, resetted at each Transmit call.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.