You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ke...@apache.org on 2012/07/06 23:28:48 UTC
[6/9] [Defect / Enhancement / New Feature] CS-15281 : Removal of
third party dependencies in Citrix code base
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/32fef61a/tools/migration/paramiko/sftp_client.py
----------------------------------------------------------------------
diff --git a/tools/migration/paramiko/sftp_client.py b/tools/migration/paramiko/sftp_client.py
deleted file mode 100644
index 5206859..0000000
--- a/tools/migration/paramiko/sftp_client.py
+++ /dev/null
@@ -1,723 +0,0 @@
-# Copyright (C) 2003-2007 Robey Pointer <ro...@gmail.com>
-# Copyright 2012 Citrix Systems, Inc. Licensed under the
-# Apache License, Version 2.0 (the "License"); you may not use this
-# file except in compliance with the License. Citrix Systems, Inc.
-# reserves all rights not expressly granted by the License.
-# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Automatically generated by addcopyright.py at 04/03/2012
-# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-
-"""
-Client-mode SFTP support.
-"""
-
-from binascii import hexlify
-import errno
-import os
-import stat
-import threading
-import time
-import weakref
-
-from paramiko.sftp import *
-from paramiko.sftp_attr import SFTPAttributes
-from paramiko.ssh_exception import SSHException
-from paramiko.sftp_file import SFTPFile
-
-
-def _to_unicode(s):
- """
- decode a string as ascii or utf8 if possible (as required by the sftp
- protocol). if neither works, just return a byte string because the server
- probably doesn't know the filename's encoding.
- """
- try:
- return s.encode('ascii')
- except UnicodeError:
- try:
- return s.decode('utf-8')
- except UnicodeError:
- return s
-
-
-class SFTPClient (BaseSFTP):
- """
- SFTP client object. C{SFTPClient} is used to open an sftp session across
- an open ssh L{Transport} and do remote file operations.
- """
-
- def __init__(self, sock):
- """
- Create an SFTP client from an existing L{Channel}. The channel
- should already have requested the C{"sftp"} subsystem.
-
- An alternate way to create an SFTP client context is by using
- L{from_transport}.
-
- @param sock: an open L{Channel} using the C{"sftp"} subsystem
- @type sock: L{Channel}
-
- @raise SSHException: if there's an exception while negotiating
- sftp
- """
- BaseSFTP.__init__(self)
- self.sock = sock
- self.ultra_debug = False
- self.request_number = 1
- # lock for request_number
- self._lock = threading.Lock()
- self._cwd = None
- # request # -> SFTPFile
- self._expecting = weakref.WeakValueDictionary()
- if type(sock) is Channel:
- # override default logger
- transport = self.sock.get_transport()
- self.logger = util.get_logger(transport.get_log_channel() + '.sftp')
- self.ultra_debug = transport.get_hexdump()
- try:
- server_version = self._send_version()
- except EOFError, x:
- raise SSHException('EOF during negotiation')
- self._log(INFO, 'Opened sftp connection (server version %d)' % server_version)
-
- def from_transport(cls, t):
- """
- Create an SFTP client channel from an open L{Transport}.
-
- @param t: an open L{Transport} which is already authenticated
- @type t: L{Transport}
- @return: a new L{SFTPClient} object, referring to an sftp session
- (channel) across the transport
- @rtype: L{SFTPClient}
- """
- chan = t.open_session()
- if chan is None:
- return None
- chan.invoke_subsystem('sftp')
- return cls(chan)
- from_transport = classmethod(from_transport)
-
- def _log(self, level, msg, *args):
- if isinstance(msg, list):
- for m in msg:
- super(SFTPClient, self)._log(level, "[chan %s] " + m, *([ self.sock.get_name() ] + list(args)))
- else:
- super(SFTPClient, self)._log(level, "[chan %s] " + msg, *([ self.sock.get_name() ] + list(args)))
-
- def close(self):
- """
- Close the SFTP session and its underlying channel.
-
- @since: 1.4
- """
- self._log(INFO, 'sftp session closed.')
- self.sock.close()
-
- def get_channel(self):
- """
- Return the underlying L{Channel} object for this SFTP session. This
- might be useful for doing things like setting a timeout on the channel.
-
- @return: the SSH channel
- @rtype: L{Channel}
-
- @since: 1.7.1
- """
- return self.sock
-
- def listdir(self, path='.'):
- """
- Return a list containing the names of the entries in the given C{path}.
- The list is in arbitrary order. It does not include the special
- entries C{'.'} and C{'..'} even if they are present in the folder.
- This method is meant to mirror C{os.listdir} as closely as possible.
- For a list of full L{SFTPAttributes} objects, see L{listdir_attr}.
-
- @param path: path to list (defaults to C{'.'})
- @type path: str
- @return: list of filenames
- @rtype: list of str
- """
- return [f.filename for f in self.listdir_attr(path)]
-
- def listdir_attr(self, path='.'):
- """
- Return a list containing L{SFTPAttributes} objects corresponding to
- files in the given C{path}. The list is in arbitrary order. It does
- not include the special entries C{'.'} and C{'..'} even if they are
- present in the folder.
-
- The returned L{SFTPAttributes} objects will each have an additional
- field: C{longname}, which may contain a formatted string of the file's
- attributes, in unix format. The content of this string will probably
- depend on the SFTP server implementation.
-
- @param path: path to list (defaults to C{'.'})
- @type path: str
- @return: list of attributes
- @rtype: list of L{SFTPAttributes}
-
- @since: 1.2
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'listdir(%r)' % path)
- t, msg = self._request(CMD_OPENDIR, path)
- if t != CMD_HANDLE:
- raise SFTPError('Expected handle')
- handle = msg.get_string()
- filelist = []
- while True:
- try:
- t, msg = self._request(CMD_READDIR, handle)
- except EOFError, e:
- # done with handle
- break
- if t != CMD_NAME:
- raise SFTPError('Expected name response')
- count = msg.get_int()
- for i in range(count):
- filename = _to_unicode(msg.get_string())
- longname = _to_unicode(msg.get_string())
- attr = SFTPAttributes._from_msg(msg, filename, longname)
- if (filename != '.') and (filename != '..'):
- filelist.append(attr)
- self._request(CMD_CLOSE, handle)
- return filelist
-
- def open(self, filename, mode='r', bufsize=-1):
- """
- Open a file on the remote server. The arguments are the same as for
- python's built-in C{file} (aka C{open}). A file-like object is
- returned, which closely mimics the behavior of a normal python file
- object.
-
- The mode indicates how the file is to be opened: C{'r'} for reading,
- C{'w'} for writing (truncating an existing file), C{'a'} for appending,
- C{'r+'} for reading/writing, C{'w+'} for reading/writing (truncating an
- existing file), C{'a+'} for reading/appending. The python C{'b'} flag
- is ignored, since SSH treats all files as binary. The C{'U'} flag is
- supported in a compatible way.
-
- Since 1.5.2, an C{'x'} flag indicates that the operation should only
- succeed if the file was created and did not previously exist. This has
- no direct mapping to python's file flags, but is commonly known as the
- C{O_EXCL} flag in posix.
-
- The file will be buffered in standard python style by default, but
- can be altered with the C{bufsize} parameter. C{0} turns off
- buffering, C{1} uses line buffering, and any number greater than 1
- (C{>1}) uses that specific buffer size.
-
- @param filename: name of the file to open
- @type filename: str
- @param mode: mode (python-style) to open in
- @type mode: str
- @param bufsize: desired buffering (-1 = default buffer size)
- @type bufsize: int
- @return: a file object representing the open file
- @rtype: SFTPFile
-
- @raise IOError: if the file could not be opened.
- """
- filename = self._adjust_cwd(filename)
- self._log(DEBUG, 'open(%r, %r)' % (filename, mode))
- imode = 0
- if ('r' in mode) or ('+' in mode):
- imode |= SFTP_FLAG_READ
- if ('w' in mode) or ('+' in mode) or ('a' in mode):
- imode |= SFTP_FLAG_WRITE
- if ('w' in mode):
- imode |= SFTP_FLAG_CREATE | SFTP_FLAG_TRUNC
- if ('a' in mode):
- imode |= SFTP_FLAG_CREATE | SFTP_FLAG_APPEND
- if ('x' in mode):
- imode |= SFTP_FLAG_CREATE | SFTP_FLAG_EXCL
- attrblock = SFTPAttributes()
- t, msg = self._request(CMD_OPEN, filename, imode, attrblock)
- if t != CMD_HANDLE:
- raise SFTPError('Expected handle')
- handle = msg.get_string()
- self._log(DEBUG, 'open(%r, %r) -> %s' % (filename, mode, hexlify(handle)))
- return SFTPFile(self, handle, mode, bufsize)
-
- # python continues to vacillate about "open" vs "file"...
- file = open
-
- def remove(self, path):
- """
- Remove the file at the given path. This only works on files; for
- removing folders (directories), use L{rmdir}.
-
- @param path: path (absolute or relative) of the file to remove
- @type path: str
-
- @raise IOError: if the path refers to a folder (directory)
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'remove(%r)' % path)
- self._request(CMD_REMOVE, path)
-
- unlink = remove
-
- def rename(self, oldpath, newpath):
- """
- Rename a file or folder from C{oldpath} to C{newpath}.
-
- @param oldpath: existing name of the file or folder
- @type oldpath: str
- @param newpath: new name for the file or folder
- @type newpath: str
-
- @raise IOError: if C{newpath} is a folder, or something else goes
- wrong
- """
- oldpath = self._adjust_cwd(oldpath)
- newpath = self._adjust_cwd(newpath)
- self._log(DEBUG, 'rename(%r, %r)' % (oldpath, newpath))
- self._request(CMD_RENAME, oldpath, newpath)
-
- def mkdir(self, path, mode=0777):
- """
- Create a folder (directory) named C{path} with numeric mode C{mode}.
- The default mode is 0777 (octal). On some systems, mode is ignored.
- Where it is used, the current umask value is first masked out.
-
- @param path: name of the folder to create
- @type path: str
- @param mode: permissions (posix-style) for the newly-created folder
- @type mode: int
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'mkdir(%r, %r)' % (path, mode))
- attr = SFTPAttributes()
- attr.st_mode = mode
- self._request(CMD_MKDIR, path, attr)
-
- def rmdir(self, path):
- """
- Remove the folder named C{path}.
-
- @param path: name of the folder to remove
- @type path: str
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'rmdir(%r)' % path)
- self._request(CMD_RMDIR, path)
-
- def stat(self, path):
- """
- Retrieve information about a file on the remote system. The return
- value is an object whose attributes correspond to the attributes of
- python's C{stat} structure as returned by C{os.stat}, except that it
- contains fewer fields. An SFTP server may return as much or as little
- info as it wants, so the results may vary from server to server.
-
- Unlike a python C{stat} object, the result may not be accessed as a
- tuple. This is mostly due to the author's slack factor.
-
- The fields supported are: C{st_mode}, C{st_size}, C{st_uid}, C{st_gid},
- C{st_atime}, and C{st_mtime}.
-
- @param path: the filename to stat
- @type path: str
- @return: an object containing attributes about the given file
- @rtype: SFTPAttributes
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'stat(%r)' % path)
- t, msg = self._request(CMD_STAT, path)
- if t != CMD_ATTRS:
- raise SFTPError('Expected attributes')
- return SFTPAttributes._from_msg(msg)
-
- def lstat(self, path):
- """
- Retrieve information about a file on the remote system, without
- following symbolic links (shortcuts). This otherwise behaves exactly
- the same as L{stat}.
-
- @param path: the filename to stat
- @type path: str
- @return: an object containing attributes about the given file
- @rtype: SFTPAttributes
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'lstat(%r)' % path)
- t, msg = self._request(CMD_LSTAT, path)
- if t != CMD_ATTRS:
- raise SFTPError('Expected attributes')
- return SFTPAttributes._from_msg(msg)
-
- def symlink(self, source, dest):
- """
- Create a symbolic link (shortcut) of the C{source} path at
- C{destination}.
-
- @param source: path of the original file
- @type source: str
- @param dest: path of the newly created symlink
- @type dest: str
- """
- dest = self._adjust_cwd(dest)
- self._log(DEBUG, 'symlink(%r, %r)' % (source, dest))
- if type(source) is unicode:
- source = source.encode('utf-8')
- self._request(CMD_SYMLINK, source, dest)
-
- def chmod(self, path, mode):
- """
- Change the mode (permissions) of a file. The permissions are
- unix-style and identical to those used by python's C{os.chmod}
- function.
-
- @param path: path of the file to change the permissions of
- @type path: str
- @param mode: new permissions
- @type mode: int
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'chmod(%r, %r)' % (path, mode))
- attr = SFTPAttributes()
- attr.st_mode = mode
- self._request(CMD_SETSTAT, path, attr)
-
- def chown(self, path, uid, gid):
- """
- Change the owner (C{uid}) and group (C{gid}) of a file. As with
- python's C{os.chown} function, you must pass both arguments, so if you
- only want to change one, use L{stat} first to retrieve the current
- owner and group.
-
- @param path: path of the file to change the owner and group of
- @type path: str
- @param uid: new owner's uid
- @type uid: int
- @param gid: new group id
- @type gid: int
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'chown(%r, %r, %r)' % (path, uid, gid))
- attr = SFTPAttributes()
- attr.st_uid, attr.st_gid = uid, gid
- self._request(CMD_SETSTAT, path, attr)
-
- def utime(self, path, times):
- """
- Set the access and modified times of the file specified by C{path}. If
- C{times} is C{None}, then the file's access and modified times are set
- to the current time. Otherwise, C{times} must be a 2-tuple of numbers,
- of the form C{(atime, mtime)}, which is used to set the access and
- modified times, respectively. This bizarre API is mimicked from python
- for the sake of consistency -- I apologize.
-
- @param path: path of the file to modify
- @type path: str
- @param times: C{None} or a tuple of (access time, modified time) in
- standard internet epoch time (seconds since 01 January 1970 GMT)
- @type times: tuple(int)
- """
- path = self._adjust_cwd(path)
- if times is None:
- times = (time.time(), time.time())
- self._log(DEBUG, 'utime(%r, %r)' % (path, times))
- attr = SFTPAttributes()
- attr.st_atime, attr.st_mtime = times
- self._request(CMD_SETSTAT, path, attr)
-
- def truncate(self, path, size):
- """
- Change the size of the file specified by C{path}. This usually extends
- or shrinks the size of the file, just like the C{truncate()} method on
- python file objects.
-
- @param path: path of the file to modify
- @type path: str
- @param size: the new size of the file
- @type size: int or long
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'truncate(%r, %r)' % (path, size))
- attr = SFTPAttributes()
- attr.st_size = size
- self._request(CMD_SETSTAT, path, attr)
-
- def readlink(self, path):
- """
- Return the target of a symbolic link (shortcut). You can use
- L{symlink} to create these. The result may be either an absolute or
- relative pathname.
-
- @param path: path of the symbolic link file
- @type path: str
- @return: target path
- @rtype: str
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'readlink(%r)' % path)
- t, msg = self._request(CMD_READLINK, path)
- if t != CMD_NAME:
- raise SFTPError('Expected name response')
- count = msg.get_int()
- if count == 0:
- return None
- if count != 1:
- raise SFTPError('Readlink returned %d results' % count)
- return _to_unicode(msg.get_string())
-
- def normalize(self, path):
- """
- Return the normalized path (on the server) of a given path. This
- can be used to quickly resolve symbolic links or determine what the
- server is considering to be the "current folder" (by passing C{'.'}
- as C{path}).
-
- @param path: path to be normalized
- @type path: str
- @return: normalized form of the given path
- @rtype: str
-
- @raise IOError: if the path can't be resolved on the server
- """
- path = self._adjust_cwd(path)
- self._log(DEBUG, 'normalize(%r)' % path)
- t, msg = self._request(CMD_REALPATH, path)
- if t != CMD_NAME:
- raise SFTPError('Expected name response')
- count = msg.get_int()
- if count != 1:
- raise SFTPError('Realpath returned %d results' % count)
- return _to_unicode(msg.get_string())
-
- def chdir(self, path):
- """
- Change the "current directory" of this SFTP session. Since SFTP
- doesn't really have the concept of a current working directory, this
- is emulated by paramiko. Once you use this method to set a working
- directory, all operations on this SFTPClient object will be relative
- to that path. You can pass in C{None} to stop using a current working
- directory.
-
- @param path: new current working directory
- @type path: str
-
- @raise IOError: if the requested path doesn't exist on the server
-
- @since: 1.4
- """
- if path is None:
- self._cwd = None
- return
- if not stat.S_ISDIR(self.stat(path).st_mode):
- raise SFTPError(errno.ENOTDIR, "%s: %s" % (os.strerror(errno.ENOTDIR), path))
- self._cwd = self.normalize(path).encode('utf-8')
-
- def getcwd(self):
- """
- Return the "current working directory" for this SFTP session, as
- emulated by paramiko. If no directory has been set with L{chdir},
- this method will return C{None}.
-
- @return: the current working directory on the server, or C{None}
- @rtype: str
-
- @since: 1.4
- """
- return self._cwd
-
- def put(self, localpath, remotepath, callback=None):
- """
- Copy a local file (C{localpath}) to the SFTP server as C{remotepath}.
- Any exception raised by operations will be passed through. This
- method is primarily provided as a convenience.
-
- The SFTP operations use pipelining for speed.
-
- @param localpath: the local file to copy
- @type localpath: str
- @param remotepath: the destination path on the SFTP server
- @type remotepath: str
- @param callback: optional callback function that accepts the bytes
- transferred so far and the total bytes to be transferred
- (since 1.7.4)
- @type callback: function(int, int)
- @return: an object containing attributes about the given file
- (since 1.7.4)
- @rtype: SFTPAttributes
-
- @since: 1.4
- """
- file_size = os.stat(localpath).st_size
- fl = file(localpath, 'rb')
- try:
- fr = self.file(remotepath, 'wb')
- fr.set_pipelined(True)
- size = 0
- try:
- while True:
- data = fl.read(32768)
- if len(data) == 0:
- break
- fr.write(data)
- size += len(data)
- if callback is not None:
- callback(size, file_size)
- finally:
- fr.close()
- finally:
- fl.close()
- s = self.stat(remotepath)
- if s.st_size != size:
- raise IOError('size mismatch in put! %d != %d' % (s.st_size, size))
- return s
-
- def get(self, remotepath, localpath, callback=None):
- """
- Copy a remote file (C{remotepath}) from the SFTP server to the local
- host as C{localpath}. Any exception raised by operations will be
- passed through. This method is primarily provided as a convenience.
-
- @param remotepath: the remote file to copy
- @type remotepath: str
- @param localpath: the destination path on the local host
- @type localpath: str
- @param callback: optional callback function that accepts the bytes
- transferred so far and the total bytes to be transferred
- (since 1.7.4)
- @type callback: function(int, int)
-
- @since: 1.4
- """
- fr = self.file(remotepath, 'rb')
- file_size = self.stat(remotepath).st_size
- fr.prefetch()
- try:
- fl = file(localpath, 'wb')
- try:
- size = 0
- while True:
- data = fr.read(32768)
- if len(data) == 0:
- break
- fl.write(data)
- size += len(data)
- if callback is not None:
- callback(size, file_size)
- finally:
- fl.close()
- finally:
- fr.close()
- s = os.stat(localpath)
- if s.st_size != size:
- raise IOError('size mismatch in get! %d != %d' % (s.st_size, size))
-
-
- ### internals...
-
-
- def _request(self, t, *arg):
- num = self._async_request(type(None), t, *arg)
- return self._read_response(num)
-
- def _async_request(self, fileobj, t, *arg):
- # this method may be called from other threads (prefetch)
- self._lock.acquire()
- try:
- msg = Message()
- msg.add_int(self.request_number)
- for item in arg:
- if type(item) is int:
- msg.add_int(item)
- elif type(item) is long:
- msg.add_int64(item)
- elif type(item) is str:
- msg.add_string(item)
- elif type(item) is SFTPAttributes:
- item._pack(msg)
- else:
- raise Exception('unknown type for %r type %r' % (item, type(item)))
- num = self.request_number
- self._expecting[num] = fileobj
- self._send_packet(t, str(msg))
- self.request_number += 1
- finally:
- self._lock.release()
- return num
-
- def _read_response(self, waitfor=None):
- while True:
- try:
- t, data = self._read_packet()
- except EOFError, e:
- raise SSHException('Server connection dropped: %s' % (str(e),))
- msg = Message(data)
- num = msg.get_int()
- if num not in self._expecting:
- # might be response for a file that was closed before responses came back
- self._log(DEBUG, 'Unexpected response #%d' % (num,))
- if waitfor is None:
- # just doing a single check
- break
- continue
- fileobj = self._expecting[num]
- del self._expecting[num]
- if num == waitfor:
- # synchronous
- if t == CMD_STATUS:
- self._convert_status(msg)
- return t, msg
- if fileobj is not type(None):
- fileobj._async_response(t, msg)
- if waitfor is None:
- # just doing a single check
- break
- return (None, None)
-
- def _finish_responses(self, fileobj):
- while fileobj in self._expecting.values():
- self._read_response()
- fileobj._check_exception()
-
- def _convert_status(self, msg):
- """
- Raises EOFError or IOError on error status; otherwise does nothing.
- """
- code = msg.get_int()
- text = msg.get_string()
- if code == SFTP_OK:
- return
- elif code == SFTP_EOF:
- raise EOFError(text)
- elif code == SFTP_NO_SUCH_FILE:
- # clever idea from john a. meinel: map the error codes to errno
- raise IOError(errno.ENOENT, text)
- elif code == SFTP_PERMISSION_DENIED:
- raise IOError(errno.EACCES, text)
- else:
- raise IOError(text)
-
- def _adjust_cwd(self, path):
- """
- Return an adjusted path if we're emulating a "current working
- directory" for the server.
- """
- if type(path) is unicode:
- path = path.encode('utf-8')
- if self._cwd is None:
- return path
- if (len(path) > 0) and (path[0] == '/'):
- # absolute path
- return path
- if self._cwd == '/':
- return self._cwd + path
- return self._cwd + '/' + path
-
-
-class SFTP (SFTPClient):
- "an alias for L{SFTPClient} for backwards compatability"
- pass
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/32fef61a/tools/migration/paramiko/sftp_file.py
----------------------------------------------------------------------
diff --git a/tools/migration/paramiko/sftp_file.py b/tools/migration/paramiko/sftp_file.py
deleted file mode 100644
index 5f4e539..0000000
--- a/tools/migration/paramiko/sftp_file.py
+++ /dev/null
@@ -1,473 +0,0 @@
-# Copyright (C) 2003-2007 Robey Pointer <ro...@gmail.com>
-# Copyright 2012 Citrix Systems, Inc. Licensed under the
-# Apache License, Version 2.0 (the "License"); you may not use this
-# file except in compliance with the License. Citrix Systems, Inc.
-# reserves all rights not expressly granted by the License.
-# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Automatically generated by addcopyright.py at 04/03/2012
-# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-
-"""
-L{SFTPFile}
-"""
-
-from binascii import hexlify
-import socket
-import threading
-import time
-
-from paramiko.common import *
-from paramiko.sftp import *
-from paramiko.file import BufferedFile
-from paramiko.sftp_attr import SFTPAttributes
-
-
-class SFTPFile (BufferedFile):
- """
- Proxy object for a file on the remote server, in client mode SFTP.
- """
-
- # Some sftp servers will choke if you send read/write requests larger than
- # this size.
- MAX_REQUEST_SIZE = 32768
-
- def __init__(self, sftp, handle, mode='r', bufsize=-1):
- BufferedFile.__init__(self)
- self.sftp = sftp
- self.handle = handle
- BufferedFile._set_mode(self, mode, bufsize)
- self.pipelined = False
- self._prefetching = False
- self._prefetch_done = False
- self._prefetch_data = {}
- self._prefetch_reads = []
- self._saved_exception = None
-
- def __del__(self):
- self._close(async=True)
-
- def close(self):
- self._close(async=False)
-
- def _close(self, async=False):
- # We allow double-close without signaling an error, because real
- # Python file objects do. However, we must protect against actually
- # sending multiple CMD_CLOSE packets, because after we close our
- # handle, the same handle may be re-allocated by the server, and we
- # may end up mysteriously closing some random other file. (This is
- # especially important because we unconditionally call close() from
- # __del__.)
- if self._closed:
- return
- self.sftp._log(DEBUG, 'close(%s)' % hexlify(self.handle))
- if self.pipelined:
- self.sftp._finish_responses(self)
- BufferedFile.close(self)
- try:
- if async:
- # GC'd file handle could be called from an arbitrary thread -- don't wait for a response
- self.sftp._async_request(type(None), CMD_CLOSE, self.handle)
- else:
- self.sftp._request(CMD_CLOSE, self.handle)
- except EOFError:
- # may have outlived the Transport connection
- pass
- except (IOError, socket.error):
- # may have outlived the Transport connection
- pass
-
- def _data_in_prefetch_requests(self, offset, size):
- k = [i for i in self._prefetch_reads if i[0] <= offset]
- if len(k) == 0:
- return False
- k.sort(lambda x, y: cmp(x[0], y[0]))
- buf_offset, buf_size = k[-1]
- if buf_offset + buf_size <= offset:
- # prefetch request ends before this one begins
- return False
- if buf_offset + buf_size >= offset + size:
- # inclusive
- return True
- # well, we have part of the request. see if another chunk has the rest.
- return self._data_in_prefetch_requests(buf_offset + buf_size, offset + size - buf_offset - buf_size)
-
- def _data_in_prefetch_buffers(self, offset):
- """
- if a block of data is present in the prefetch buffers, at the given
- offset, return the offset of the relevant prefetch buffer. otherwise,
- return None. this guarantees nothing about the number of bytes
- collected in the prefetch buffer so far.
- """
- k = [i for i in self._prefetch_data.keys() if i <= offset]
- if len(k) == 0:
- return None
- index = max(k)
- buf_offset = offset - index
- if buf_offset >= len(self._prefetch_data[index]):
- # it's not here
- return None
- return index
-
- def _read_prefetch(self, size):
- """
- read data out of the prefetch buffer, if possible. if the data isn't
- in the buffer, return None. otherwise, behaves like a normal read.
- """
- # while not closed, and haven't fetched past the current position, and haven't reached EOF...
- while True:
- offset = self._data_in_prefetch_buffers(self._realpos)
- if offset is not None:
- break
- if self._prefetch_done or self._closed:
- break
- self.sftp._read_response()
- self._check_exception()
- if offset is None:
- self._prefetching = False
- return None
- prefetch = self._prefetch_data[offset]
- del self._prefetch_data[offset]
-
- buf_offset = self._realpos - offset
- if buf_offset > 0:
- self._prefetch_data[offset] = prefetch[:buf_offset]
- prefetch = prefetch[buf_offset:]
- if size < len(prefetch):
- self._prefetch_data[self._realpos + size] = prefetch[size:]
- prefetch = prefetch[:size]
- return prefetch
-
- def _read(self, size):
- size = min(size, self.MAX_REQUEST_SIZE)
- if self._prefetching:
- data = self._read_prefetch(size)
- if data is not None:
- return data
- t, msg = self.sftp._request(CMD_READ, self.handle, long(self._realpos), int(size))
- if t != CMD_DATA:
- raise SFTPError('Expected data')
- return msg.get_string()
-
- def _write(self, data):
- # may write less than requested if it would exceed max packet size
- chunk = min(len(data), self.MAX_REQUEST_SIZE)
- req = self.sftp._async_request(type(None), CMD_WRITE, self.handle, long(self._realpos), str(data[:chunk]))
- if not self.pipelined or self.sftp.sock.recv_ready():
- t, msg = self.sftp._read_response(req)
- if t != CMD_STATUS:
- raise SFTPError('Expected status')
- # convert_status already called
- return chunk
-
- def settimeout(self, timeout):
- """
- Set a timeout on read/write operations on the underlying socket or
- ssh L{Channel}.
-
- @see: L{Channel.settimeout}
- @param timeout: seconds to wait for a pending read/write operation
- before raising C{socket.timeout}, or C{None} for no timeout
- @type timeout: float
- """
- self.sftp.sock.settimeout(timeout)
-
- def gettimeout(self):
- """
- Returns the timeout in seconds (as a float) associated with the socket
- or ssh L{Channel} used for this file.
-
- @see: L{Channel.gettimeout}
- @rtype: float
- """
- return self.sftp.sock.gettimeout()
-
- def setblocking(self, blocking):
- """
- Set blocking or non-blocking mode on the underiying socket or ssh
- L{Channel}.
-
- @see: L{Channel.setblocking}
- @param blocking: 0 to set non-blocking mode; non-0 to set blocking
- mode.
- @type blocking: int
- """
- self.sftp.sock.setblocking(blocking)
-
- def seek(self, offset, whence=0):
- self.flush()
- if whence == self.SEEK_SET:
- self._realpos = self._pos = offset
- elif whence == self.SEEK_CUR:
- self._pos += offset
- self._realpos = self._pos
- else:
- self._realpos = self._pos = self._get_size() + offset
- self._rbuffer = ''
-
- def stat(self):
- """
- Retrieve information about this file from the remote system. This is
- exactly like L{SFTP.stat}, except that it operates on an already-open
- file.
-
- @return: an object containing attributes about this file.
- @rtype: SFTPAttributes
- """
- t, msg = self.sftp._request(CMD_FSTAT, self.handle)
- if t != CMD_ATTRS:
- raise SFTPError('Expected attributes')
- return SFTPAttributes._from_msg(msg)
-
- def chmod(self, mode):
- """
- Change the mode (permissions) of this file. The permissions are
- unix-style and identical to those used by python's C{os.chmod}
- function.
-
- @param mode: new permissions
- @type mode: int
- """
- self.sftp._log(DEBUG, 'chmod(%s, %r)' % (hexlify(self.handle), mode))
- attr = SFTPAttributes()
- attr.st_mode = mode
- self.sftp._request(CMD_FSETSTAT, self.handle, attr)
-
- def chown(self, uid, gid):
- """
- Change the owner (C{uid}) and group (C{gid}) of this file. As with
- python's C{os.chown} function, you must pass both arguments, so if you
- only want to change one, use L{stat} first to retrieve the current
- owner and group.
-
- @param uid: new owner's uid
- @type uid: int
- @param gid: new group id
- @type gid: int
- """
- self.sftp._log(DEBUG, 'chown(%s, %r, %r)' % (hexlify(self.handle), uid, gid))
- attr = SFTPAttributes()
- attr.st_uid, attr.st_gid = uid, gid
- self.sftp._request(CMD_FSETSTAT, self.handle, attr)
-
- def utime(self, times):
- """
- Set the access and modified times of this file. If
- C{times} is C{None}, then the file's access and modified times are set
- to the current time. Otherwise, C{times} must be a 2-tuple of numbers,
- of the form C{(atime, mtime)}, which is used to set the access and
- modified times, respectively. This bizarre API is mimicked from python
- for the sake of consistency -- I apologize.
-
- @param times: C{None} or a tuple of (access time, modified time) in
- standard internet epoch time (seconds since 01 January 1970 GMT)
- @type times: tuple(int)
- """
- if times is None:
- times = (time.time(), time.time())
- self.sftp._log(DEBUG, 'utime(%s, %r)' % (hexlify(self.handle), times))
- attr = SFTPAttributes()
- attr.st_atime, attr.st_mtime = times
- self.sftp._request(CMD_FSETSTAT, self.handle, attr)
-
- def truncate(self, size):
- """
- Change the size of this file. This usually extends
- or shrinks the size of the file, just like the C{truncate()} method on
- python file objects.
-
- @param size: the new size of the file
- @type size: int or long
- """
- self.sftp._log(DEBUG, 'truncate(%s, %r)' % (hexlify(self.handle), size))
- attr = SFTPAttributes()
- attr.st_size = size
- self.sftp._request(CMD_FSETSTAT, self.handle, attr)
-
- def check(self, hash_algorithm, offset=0, length=0, block_size=0):
- """
- Ask the server for a hash of a section of this file. This can be used
- to verify a successful upload or download, or for various rsync-like
- operations.
-
- The file is hashed from C{offset}, for C{length} bytes. If C{length}
- is 0, the remainder of the file is hashed. Thus, if both C{offset}
- and C{length} are zero, the entire file is hashed.
-
- Normally, C{block_size} will be 0 (the default), and this method will
- return a byte string representing the requested hash (for example, a
- string of length 16 for MD5, or 20 for SHA-1). If a non-zero
- C{block_size} is given, each chunk of the file (from C{offset} to
- C{offset + length}) of C{block_size} bytes is computed as a separate
- hash. The hash results are all concatenated and returned as a single
- string.
-
- For example, C{check('sha1', 0, 1024, 512)} will return a string of
- length 40. The first 20 bytes will be the SHA-1 of the first 512 bytes
- of the file, and the last 20 bytes will be the SHA-1 of the next 512
- bytes.
-
- @param hash_algorithm: the name of the hash algorithm to use (normally
- C{"sha1"} or C{"md5"})
- @type hash_algorithm: str
- @param offset: offset into the file to begin hashing (0 means to start
- from the beginning)
- @type offset: int or long
- @param length: number of bytes to hash (0 means continue to the end of
- the file)
- @type length: int or long
- @param block_size: number of bytes to hash per result (must not be less
- than 256; 0 means to compute only one hash of the entire segment)
- @type block_size: int
- @return: string of bytes representing the hash of each block,
- concatenated together
- @rtype: str
-
- @note: Many (most?) servers don't support this extension yet.
-
- @raise IOError: if the server doesn't support the "check-file"
- extension, or possibly doesn't support the hash algorithm
- requested
-
- @since: 1.4
- """
- t, msg = self.sftp._request(CMD_EXTENDED, 'check-file', self.handle,
- hash_algorithm, long(offset), long(length), block_size)
- ext = msg.get_string()
- alg = msg.get_string()
- data = msg.get_remainder()
- return data
-
- def set_pipelined(self, pipelined=True):
- """
- Turn on/off the pipelining of write operations to this file. When
- pipelining is on, paramiko won't wait for the server response after
- each write operation. Instead, they're collected as they come in.
- At the first non-write operation (including L{close}), all remaining
- server responses are collected. This means that if there was an error
- with one of your later writes, an exception might be thrown from
- within L{close} instead of L{write}.
-
- By default, files are I{not} pipelined.
-
- @param pipelined: C{True} if pipelining should be turned on for this
- file; C{False} otherwise
- @type pipelined: bool
-
- @since: 1.5
- """
- self.pipelined = pipelined
-
- def prefetch(self):
- """
- Pre-fetch the remaining contents of this file in anticipation of
- future L{read} calls. If reading the entire file, pre-fetching can
- dramatically improve the download speed by avoiding roundtrip latency.
- The file's contents are incrementally buffered in a background thread.
-
- The prefetched data is stored in a buffer until read via the L{read}
- method. Once data has been read, it's removed from the buffer. The
- data may be read in a random order (using L{seek}); chunks of the
- buffer that haven't been read will continue to be buffered.
-
- @since: 1.5.1
- """
- size = self.stat().st_size
- # queue up async reads for the rest of the file
- chunks = []
- n = self._realpos
- while n < size:
- chunk = min(self.MAX_REQUEST_SIZE, size - n)
- chunks.append((n, chunk))
- n += chunk
- if len(chunks) > 0:
- self._start_prefetch(chunks)
-
- def readv(self, chunks):
- """
- Read a set of blocks from the file by (offset, length). This is more
- efficient than doing a series of L{seek} and L{read} calls, since the
- prefetch machinery is used to retrieve all the requested blocks at
- once.
-
- @param chunks: a list of (offset, length) tuples indicating which
- sections of the file to read
- @type chunks: list(tuple(long, int))
- @return: a list of blocks read, in the same order as in C{chunks}
- @rtype: list(str)
-
- @since: 1.5.4
- """
- self.sftp._log(DEBUG, 'readv(%s, %r)' % (hexlify(self.handle), chunks))
-
- read_chunks = []
- for offset, size in chunks:
- # don't fetch data that's already in the prefetch buffer
- if self._data_in_prefetch_buffers(offset) or self._data_in_prefetch_requests(offset, size):
- continue
-
- # break up anything larger than the max read size
- while size > 0:
- chunk_size = min(size, self.MAX_REQUEST_SIZE)
- read_chunks.append((offset, chunk_size))
- offset += chunk_size
- size -= chunk_size
-
- self._start_prefetch(read_chunks)
- # now we can just devolve to a bunch of read()s :)
- for x in chunks:
- self.seek(x[0])
- yield self.read(x[1])
-
-
- ### internals...
-
-
- def _get_size(self):
- try:
- return self.stat().st_size
- except:
- return 0
-
- def _start_prefetch(self, chunks):
- self._prefetching = True
- self._prefetch_done = False
- self._prefetch_reads.extend(chunks)
-
- t = threading.Thread(target=self._prefetch_thread, args=(chunks,))
- t.setDaemon(True)
- t.start()
-
- def _prefetch_thread(self, chunks):
- # do these read requests in a temporary thread because there may be
- # a lot of them, so it may block.
- for offset, length in chunks:
- self.sftp._async_request(self, CMD_READ, self.handle, long(offset), int(length))
-
- def _async_response(self, t, msg):
- if t == CMD_STATUS:
- # save exception and re-raise it on next file operation
- try:
- self.sftp._convert_status(msg)
- except Exception, x:
- self._saved_exception = x
- return
- if t != CMD_DATA:
- raise SFTPError('Expected data')
- data = msg.get_string()
- offset, length = self._prefetch_reads.pop(0)
- self._prefetch_data[offset] = data
- if len(self._prefetch_reads) == 0:
- self._prefetch_done = True
-
- def _check_exception(self):
- "if there's a saved exception, raise & clear it"
- if self._saved_exception is not None:
- x = self._saved_exception
- self._saved_exception = None
- raise x
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/32fef61a/tools/migration/paramiko/sftp_handle.py
----------------------------------------------------------------------
diff --git a/tools/migration/paramiko/sftp_handle.py b/tools/migration/paramiko/sftp_handle.py
deleted file mode 100644
index 0576eeb..0000000
--- a/tools/migration/paramiko/sftp_handle.py
+++ /dev/null
@@ -1,199 +0,0 @@
-# Copyright (C) 2003-2007 Robey Pointer <ro...@gmail.com>
-# Copyright 2012 Citrix Systems, Inc. Licensed under the
-# Apache License, Version 2.0 (the "License"); you may not use this
-# file except in compliance with the License. Citrix Systems, Inc.
-# reserves all rights not expressly granted by the License.
-# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Automatically generated by addcopyright.py at 04/03/2012
-# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-
-"""
-Abstraction of an SFTP file handle (for server mode).
-"""
-
-import os
-
-from paramiko.common import *
-from paramiko.sftp import *
-
-
-class SFTPHandle (object):
- """
- Abstract object representing a handle to an open file (or folder) in an
- SFTP server implementation. Each handle has a string representation used
- by the client to refer to the underlying file.
-
- Server implementations can (and should) subclass SFTPHandle to implement
- features of a file handle, like L{stat} or L{chattr}.
- """
- def __init__(self, flags=0):
- """
- Create a new file handle representing a local file being served over
- SFTP. If C{flags} is passed in, it's used to determine if the file
- is open in append mode.
-
- @param flags: optional flags as passed to L{SFTPServerInterface.open}
- @type flags: int
- """
- self.__flags = flags
- self.__name = None
- # only for handles to folders:
- self.__files = { }
- self.__tell = None
-
- def close(self):
- """
- When a client closes a file, this method is called on the handle.
- Normally you would use this method to close the underlying OS level
- file object(s).
-
- The default implementation checks for attributes on C{self} named
- C{readfile} and/or C{writefile}, and if either or both are present,
- their C{close()} methods are called. This means that if you are
- using the default implementations of L{read} and L{write}, this
- method's default implementation should be fine also.
- """
- readfile = getattr(self, 'readfile', None)
- if readfile is not None:
- readfile.close()
- writefile = getattr(self, 'writefile', None)
- if writefile is not None:
- writefile.close()
-
- def read(self, offset, length):
- """
- Read up to C{length} bytes from this file, starting at position
- C{offset}. The offset may be a python long, since SFTP allows it
- to be 64 bits.
-
- If the end of the file has been reached, this method may return an
- empty string to signify EOF, or it may also return L{SFTP_EOF}.
-
- The default implementation checks for an attribute on C{self} named
- C{readfile}, and if present, performs the read operation on the python
- file-like object found there. (This is meant as a time saver for the
- common case where you are wrapping a python file object.)
-
- @param offset: position in the file to start reading from.
- @type offset: int or long
- @param length: number of bytes to attempt to read.
- @type length: int
- @return: data read from the file, or an SFTP error code.
- @rtype: str
- """
- readfile = getattr(self, 'readfile', None)
- if readfile is None:
- return SFTP_OP_UNSUPPORTED
- try:
- if self.__tell is None:
- self.__tell = readfile.tell()
- if offset != self.__tell:
- readfile.seek(offset)
- self.__tell = offset
- data = readfile.read(length)
- except IOError, e:
- self.__tell = None
- return SFTPServer.convert_errno(e.errno)
- self.__tell += len(data)
- return data
-
- def write(self, offset, data):
- """
- Write C{data} into this file at position C{offset}. Extending the
- file past its original end is expected. Unlike python's normal
- C{write()} methods, this method cannot do a partial write: it must
- write all of C{data} or else return an error.
-
- The default implementation checks for an attribute on C{self} named
- C{writefile}, and if present, performs the write operation on the
- python file-like object found there. The attribute is named
- differently from C{readfile} to make it easy to implement read-only
- (or write-only) files, but if both attributes are present, they should
- refer to the same file.
-
- @param offset: position in the file to start reading from.
- @type offset: int or long
- @param data: data to write into the file.
- @type data: str
- @return: an SFTP error code like L{SFTP_OK}.
- """
- writefile = getattr(self, 'writefile', None)
- if writefile is None:
- return SFTP_OP_UNSUPPORTED
- try:
- # in append mode, don't care about seeking
- if (self.__flags & os.O_APPEND) == 0:
- if self.__tell is None:
- self.__tell = writefile.tell()
- if offset != self.__tell:
- writefile.seek(offset)
- self.__tell = offset
- writefile.write(data)
- writefile.flush()
- except IOError, e:
- self.__tell = None
- return SFTPServer.convert_errno(e.errno)
- if self.__tell is not None:
- self.__tell += len(data)
- return SFTP_OK
-
- def stat(self):
- """
- Return an L{SFTPAttributes} object referring to this open file, or an
- error code. This is equivalent to L{SFTPServerInterface.stat}, except
- it's called on an open file instead of a path.
-
- @return: an attributes object for the given file, or an SFTP error
- code (like L{SFTP_PERMISSION_DENIED}).
- @rtype: L{SFTPAttributes} I{or error code}
- """
- return SFTP_OP_UNSUPPORTED
-
- def chattr(self, attr):
- """
- Change the attributes of this file. The C{attr} object will contain
- only those fields provided by the client in its request, so you should
- check for the presence of fields before using them.
-
- @param attr: the attributes to change on this file.
- @type attr: L{SFTPAttributes}
- @return: an error code like L{SFTP_OK}.
- @rtype: int
- """
- return SFTP_OP_UNSUPPORTED
-
-
- ### internals...
-
-
- def _set_files(self, files):
- """
- Used by the SFTP server code to cache a directory listing. (In
- the SFTP protocol, listing a directory is a multi-stage process
- requiring a temporary handle.)
- """
- self.__files = files
-
- def _get_next_files(self):
- """
- Used by the SFTP server code to retreive a cached directory
- listing.
- """
- fnlist = self.__files[:16]
- self.__files = self.__files[16:]
- return fnlist
-
- def _get_name(self):
- return self.__name
-
- def _set_name(self, name):
- self.__name = name
-
-
-from paramiko.sftp_server import SFTPServer
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/32fef61a/tools/migration/paramiko/sftp_server.py
----------------------------------------------------------------------
diff --git a/tools/migration/paramiko/sftp_server.py b/tools/migration/paramiko/sftp_server.py
deleted file mode 100644
index db6fa27..0000000
--- a/tools/migration/paramiko/sftp_server.py
+++ /dev/null
@@ -1,441 +0,0 @@
-# Copyright (C) 2003-2007 Robey Pointer <ro...@gmail.com>
-# Copyright 2012 Citrix Systems, Inc. Licensed under the
-# Apache License, Version 2.0 (the "License"); you may not use this
-# file except in compliance with the License. Citrix Systems, Inc.
-# reserves all rights not expressly granted by the License.
-# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Automatically generated by addcopyright.py at 04/03/2012
-# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-
-"""
-Server-mode SFTP support.
-"""
-
-import os
-import errno
-
-from Crypto.Hash import MD5, SHA
-from paramiko.common import *
-from paramiko.server import SubsystemHandler
-from paramiko.sftp import *
-from paramiko.sftp_si import *
-from paramiko.sftp_attr import *
-
-
-# known hash algorithms for the "check-file" extension
-_hash_class = {
- 'sha1': SHA,
- 'md5': MD5,
-}
-
-
-class SFTPServer (BaseSFTP, SubsystemHandler):
- """
- Server-side SFTP subsystem support. Since this is a L{SubsystemHandler},
- it can be (and is meant to be) set as the handler for C{"sftp"} requests.
- Use L{Transport.set_subsystem_handler} to activate this class.
- """
-
- def __init__(self, channel, name, server, sftp_si=SFTPServerInterface, *largs, **kwargs):
- """
- The constructor for SFTPServer is meant to be called from within the
- L{Transport} as a subsystem handler. C{server} and any additional
- parameters or keyword parameters are passed from the original call to
- L{Transport.set_subsystem_handler}.
-
- @param channel: channel passed from the L{Transport}.
- @type channel: L{Channel}
- @param name: name of the requested subsystem.
- @type name: str
- @param server: the server object associated with this channel and
- subsystem
- @type server: L{ServerInterface}
- @param sftp_si: a subclass of L{SFTPServerInterface} to use for handling
- individual requests.
- @type sftp_si: class
- """
- BaseSFTP.__init__(self)
- SubsystemHandler.__init__(self, channel, name, server)
- transport = channel.get_transport()
- self.logger = util.get_logger(transport.get_log_channel() + '.sftp')
- self.ultra_debug = transport.get_hexdump()
- self.next_handle = 1
- # map of handle-string to SFTPHandle for files & folders:
- self.file_table = { }
- self.folder_table = { }
- self.server = sftp_si(server, *largs, **kwargs)
-
- def _log(self, level, msg):
- if issubclass(type(msg), list):
- for m in msg:
- super(SFTPServer, self)._log(level, "[chan " + self.sock.get_name() + "] " + m)
- else:
- super(SFTPServer, self)._log(level, "[chan " + self.sock.get_name() + "] " + msg)
-
- def start_subsystem(self, name, transport, channel):
- self.sock = channel
- self._log(DEBUG, 'Started sftp server on channel %s' % repr(channel))
- self._send_server_version()
- self.server.session_started()
- while True:
- try:
- t, data = self._read_packet()
- except EOFError:
- self._log(DEBUG, 'EOF -- end of session')
- return
- except Exception, e:
- self._log(DEBUG, 'Exception on channel: ' + str(e))
- self._log(DEBUG, util.tb_strings())
- return
- msg = Message(data)
- request_number = msg.get_int()
- try:
- self._process(t, request_number, msg)
- except Exception, e:
- self._log(DEBUG, 'Exception in server processing: ' + str(e))
- self._log(DEBUG, util.tb_strings())
- # send some kind of failure message, at least
- try:
- self._send_status(request_number, SFTP_FAILURE)
- except:
- pass
-
- def finish_subsystem(self):
- self.server.session_ended()
- super(SFTPServer, self).finish_subsystem()
- # close any file handles that were left open (so we can return them to the OS quickly)
- for f in self.file_table.itervalues():
- f.close()
- for f in self.folder_table.itervalues():
- f.close()
- self.file_table = {}
- self.folder_table = {}
-
- def convert_errno(e):
- """
- Convert an errno value (as from an C{OSError} or C{IOError}) into a
- standard SFTP result code. This is a convenience function for trapping
- exceptions in server code and returning an appropriate result.
-
- @param e: an errno code, as from C{OSError.errno}.
- @type e: int
- @return: an SFTP error code like L{SFTP_NO_SUCH_FILE}.
- @rtype: int
- """
- if e == errno.EACCES:
- # permission denied
- return SFTP_PERMISSION_DENIED
- elif (e == errno.ENOENT) or (e == errno.ENOTDIR):
- # no such file
- return SFTP_NO_SUCH_FILE
- else:
- return SFTP_FAILURE
- convert_errno = staticmethod(convert_errno)
-
- def set_file_attr(filename, attr):
- """
- Change a file's attributes on the local filesystem. The contents of
- C{attr} are used to change the permissions, owner, group ownership,
- and/or modification & access time of the file, depending on which
- attributes are present in C{attr}.
-
- This is meant to be a handy helper function for translating SFTP file
- requests into local file operations.
-
- @param filename: name of the file to alter (should usually be an
- absolute path).
- @type filename: str
- @param attr: attributes to change.
- @type attr: L{SFTPAttributes}
- """
- if sys.platform != 'win32':
- # mode operations are meaningless on win32
- if attr._flags & attr.FLAG_PERMISSIONS:
- os.chmod(filename, attr.st_mode)
- if attr._flags & attr.FLAG_UIDGID:
- os.chown(filename, attr.st_uid, attr.st_gid)
- if attr._flags & attr.FLAG_AMTIME:
- os.utime(filename, (attr.st_atime, attr.st_mtime))
- if attr._flags & attr.FLAG_SIZE:
- open(filename, 'w+').truncate(attr.st_size)
- set_file_attr = staticmethod(set_file_attr)
-
-
- ### internals...
-
-
- def _response(self, request_number, t, *arg):
- msg = Message()
- msg.add_int(request_number)
- for item in arg:
- if type(item) is int:
- msg.add_int(item)
- elif type(item) is long:
- msg.add_int64(item)
- elif type(item) is str:
- msg.add_string(item)
- elif type(item) is SFTPAttributes:
- item._pack(msg)
- else:
- raise Exception('unknown type for ' + repr(item) + ' type ' + repr(type(item)))
- self._send_packet(t, str(msg))
-
- def _send_handle_response(self, request_number, handle, folder=False):
- if not issubclass(type(handle), SFTPHandle):
- # must be error code
- self._send_status(request_number, handle)
- return
- handle._set_name('hx%d' % self.next_handle)
- self.next_handle += 1
- if folder:
- self.folder_table[handle._get_name()] = handle
- else:
- self.file_table[handle._get_name()] = handle
- self._response(request_number, CMD_HANDLE, handle._get_name())
-
- def _send_status(self, request_number, code, desc=None):
- if desc is None:
- try:
- desc = SFTP_DESC[code]
- except IndexError:
- desc = 'Unknown'
- # some clients expect a "langauge" tag at the end (but don't mind it being blank)
- self._response(request_number, CMD_STATUS, code, desc, '')
-
- def _open_folder(self, request_number, path):
- resp = self.server.list_folder(path)
- if issubclass(type(resp), list):
- # got an actual list of filenames in the folder
- folder = SFTPHandle()
- folder._set_files(resp)
- self._send_handle_response(request_number, folder, True)
- return
- # must be an error code
- self._send_status(request_number, resp)
-
- def _read_folder(self, request_number, folder):
- flist = folder._get_next_files()
- if len(flist) == 0:
- self._send_status(request_number, SFTP_EOF)
- return
- msg = Message()
- msg.add_int(request_number)
- msg.add_int(len(flist))
- for attr in flist:
- msg.add_string(attr.filename)
- msg.add_string(str(attr))
- attr._pack(msg)
- self._send_packet(CMD_NAME, str(msg))
-
- def _check_file(self, request_number, msg):
- # this extension actually comes from v6 protocol, but since it's an
- # extension, i feel like we can reasonably support it backported.
- # it's very useful for verifying uploaded files or checking for
- # rsync-like differences between local and remote files.
- handle = msg.get_string()
- alg_list = msg.get_list()
- start = msg.get_int64()
- length = msg.get_int64()
- block_size = msg.get_int()
- if handle not in self.file_table:
- self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
- return
- f = self.file_table[handle]
- for x in alg_list:
- if x in _hash_class:
- algname = x
- alg = _hash_class[x]
- break
- else:
- self._send_status(request_number, SFTP_FAILURE, 'No supported hash types found')
- return
- if length == 0:
- st = f.stat()
- if not issubclass(type(st), SFTPAttributes):
- self._send_status(request_number, st, 'Unable to stat file')
- return
- length = st.st_size - start
- if block_size == 0:
- block_size = length
- if block_size < 256:
- self._send_status(request_number, SFTP_FAILURE, 'Block size too small')
- return
-
- sum_out = ''
- offset = start
- while offset < start + length:
- blocklen = min(block_size, start + length - offset)
- # don't try to read more than about 64KB at a time
- chunklen = min(blocklen, 65536)
- count = 0
- hash_obj = alg.new()
- while count < blocklen:
- data = f.read(offset, chunklen)
- if not type(data) is str:
- self._send_status(request_number, data, 'Unable to hash file')
- return
- hash_obj.update(data)
- count += len(data)
- offset += count
- sum_out += hash_obj.digest()
-
- msg = Message()
- msg.add_int(request_number)
- msg.add_string('check-file')
- msg.add_string(algname)
- msg.add_bytes(sum_out)
- self._send_packet(CMD_EXTENDED_REPLY, str(msg))
-
- def _convert_pflags(self, pflags):
- "convert SFTP-style open() flags to python's os.open() flags"
- if (pflags & SFTP_FLAG_READ) and (pflags & SFTP_FLAG_WRITE):
- flags = os.O_RDWR
- elif pflags & SFTP_FLAG_WRITE:
- flags = os.O_WRONLY
- else:
- flags = os.O_RDONLY
- if pflags & SFTP_FLAG_APPEND:
- flags |= os.O_APPEND
- if pflags & SFTP_FLAG_CREATE:
- flags |= os.O_CREAT
- if pflags & SFTP_FLAG_TRUNC:
- flags |= os.O_TRUNC
- if pflags & SFTP_FLAG_EXCL:
- flags |= os.O_EXCL
- return flags
-
- def _process(self, t, request_number, msg):
- self._log(DEBUG, 'Request: %s' % CMD_NAMES[t])
- if t == CMD_OPEN:
- path = msg.get_string()
- flags = self._convert_pflags(msg.get_int())
- attr = SFTPAttributes._from_msg(msg)
- self._send_handle_response(request_number, self.server.open(path, flags, attr))
- elif t == CMD_CLOSE:
- handle = msg.get_string()
- if handle in self.folder_table:
- del self.folder_table[handle]
- self._send_status(request_number, SFTP_OK)
- return
- if handle in self.file_table:
- self.file_table[handle].close()
- del self.file_table[handle]
- self._send_status(request_number, SFTP_OK)
- return
- self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
- elif t == CMD_READ:
- handle = msg.get_string()
- offset = msg.get_int64()
- length = msg.get_int()
- if handle not in self.file_table:
- self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
- return
- data = self.file_table[handle].read(offset, length)
- if type(data) is str:
- if len(data) == 0:
- self._send_status(request_number, SFTP_EOF)
- else:
- self._response(request_number, CMD_DATA, data)
- else:
- self._send_status(request_number, data)
- elif t == CMD_WRITE:
- handle = msg.get_string()
- offset = msg.get_int64()
- data = msg.get_string()
- if handle not in self.file_table:
- self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
- return
- self._send_status(request_number, self.file_table[handle].write(offset, data))
- elif t == CMD_REMOVE:
- path = msg.get_string()
- self._send_status(request_number, self.server.remove(path))
- elif t == CMD_RENAME:
- oldpath = msg.get_string()
- newpath = msg.get_string()
- self._send_status(request_number, self.server.rename(oldpath, newpath))
- elif t == CMD_MKDIR:
- path = msg.get_string()
- attr = SFTPAttributes._from_msg(msg)
- self._send_status(request_number, self.server.mkdir(path, attr))
- elif t == CMD_RMDIR:
- path = msg.get_string()
- self._send_status(request_number, self.server.rmdir(path))
- elif t == CMD_OPENDIR:
- path = msg.get_string()
- self._open_folder(request_number, path)
- return
- elif t == CMD_READDIR:
- handle = msg.get_string()
- if handle not in self.folder_table:
- self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
- return
- folder = self.folder_table[handle]
- self._read_folder(request_number, folder)
- elif t == CMD_STAT:
- path = msg.get_string()
- resp = self.server.stat(path)
- if issubclass(type(resp), SFTPAttributes):
- self._response(request_number, CMD_ATTRS, resp)
- else:
- self._send_status(request_number, resp)
- elif t == CMD_LSTAT:
- path = msg.get_string()
- resp = self.server.lstat(path)
- if issubclass(type(resp), SFTPAttributes):
- self._response(request_number, CMD_ATTRS, resp)
- else:
- self._send_status(request_number, resp)
- elif t == CMD_FSTAT:
- handle = msg.get_string()
- if handle not in self.file_table:
- self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
- return
- resp = self.file_table[handle].stat()
- if issubclass(type(resp), SFTPAttributes):
- self._response(request_number, CMD_ATTRS, resp)
- else:
- self._send_status(request_number, resp)
- elif t == CMD_SETSTAT:
- path = msg.get_string()
- attr = SFTPAttributes._from_msg(msg)
- self._send_status(request_number, self.server.chattr(path, attr))
- elif t == CMD_FSETSTAT:
- handle = msg.get_string()
- attr = SFTPAttributes._from_msg(msg)
- if handle not in self.file_table:
- self._response(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
- return
- self._send_status(request_number, self.file_table[handle].chattr(attr))
- elif t == CMD_READLINK:
- path = msg.get_string()
- resp = self.server.readlink(path)
- if type(resp) is str:
- self._response(request_number, CMD_NAME, 1, resp, '', SFTPAttributes())
- else:
- self._send_status(request_number, resp)
- elif t == CMD_SYMLINK:
- # the sftp 2 draft is incorrect here! path always follows target_path
- target_path = msg.get_string()
- path = msg.get_string()
- self._send_status(request_number, self.server.symlink(target_path, path))
- elif t == CMD_REALPATH:
- path = msg.get_string()
- rpath = self.server.canonicalize(path)
- self._response(request_number, CMD_NAME, 1, rpath, '', SFTPAttributes())
- elif t == CMD_EXTENDED:
- tag = msg.get_string()
- if tag == 'check-file':
- self._check_file(request_number, msg)
- else:
- self._send_status(request_number, SFTP_OP_UNSUPPORTED)
- else:
- self._send_status(request_number, SFTP_OP_UNSUPPORTED)
-
-
-from paramiko.sftp_handle import SFTPHandle
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/32fef61a/tools/migration/paramiko/sftp_si.py
----------------------------------------------------------------------
diff --git a/tools/migration/paramiko/sftp_si.py b/tools/migration/paramiko/sftp_si.py
deleted file mode 100644
index 1d52a17..0000000
--- a/tools/migration/paramiko/sftp_si.py
+++ /dev/null
@@ -1,307 +0,0 @@
-# Copyright (C) 2003-2007 Robey Pointer <ro...@gmail.com>
-# Copyright 2012 Citrix Systems, Inc. Licensed under the
-# Apache License, Version 2.0 (the "License"); you may not use this
-# file except in compliance with the License. Citrix Systems, Inc.
-# reserves all rights not expressly granted by the License.
-# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Automatically generated by addcopyright.py at 04/03/2012
-# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-
-"""
-L{SFTPServerInterface} is an interface to override for SFTP server support.
-"""
-
-import os
-
-from paramiko.common import *
-from paramiko.sftp import *
-
-
-class SFTPServerInterface (object):
- """
- This class defines an interface for controlling the behavior of paramiko
- when using the L{SFTPServer} subsystem to provide an SFTP server.
-
- Methods on this class are called from the SFTP session's thread, so you can
- block as long as necessary without affecting other sessions (even other
- SFTP sessions). However, raising an exception will usually cause the SFTP
- session to abruptly end, so you will usually want to catch exceptions and
- return an appropriate error code.
-
- All paths are in string form instead of unicode because not all SFTP
- clients & servers obey the requirement that paths be encoded in UTF-8.
- """
-
- def __init__ (self, server, *largs, **kwargs):
- """
- Create a new SFTPServerInterface object. This method does nothing by
- default and is meant to be overridden by subclasses.
-
- @param server: the server object associated with this channel and
- SFTP subsystem
- @type server: L{ServerInterface}
- """
- super(SFTPServerInterface, self).__init__(*largs, **kwargs)
-
- def session_started(self):
- """
- The SFTP server session has just started. This method is meant to be
- overridden to perform any necessary setup before handling callbacks
- from SFTP operations.
- """
- pass
-
- def session_ended(self):
- """
- The SFTP server session has just ended, either cleanly or via an
- exception. This method is meant to be overridden to perform any
- necessary cleanup before this C{SFTPServerInterface} object is
- destroyed.
- """
- pass
-
- def open(self, path, flags, attr):
- """
- Open a file on the server and create a handle for future operations
- on that file. On success, a new object subclassed from L{SFTPHandle}
- should be returned. This handle will be used for future operations
- on the file (read, write, etc). On failure, an error code such as
- L{SFTP_PERMISSION_DENIED} should be returned.
-
- C{flags} contains the requested mode for opening (read-only,
- write-append, etc) as a bitset of flags from the C{os} module:
- - C{os.O_RDONLY}
- - C{os.O_WRONLY}
- - C{os.O_RDWR}
- - C{os.O_APPEND}
- - C{os.O_CREAT}
- - C{os.O_TRUNC}
- - C{os.O_EXCL}
- (One of C{os.O_RDONLY}, C{os.O_WRONLY}, or C{os.O_RDWR} will always
- be set.)
-
- The C{attr} object contains requested attributes of the file if it
- has to be created. Some or all attribute fields may be missing if
- the client didn't specify them.
-
- @note: The SFTP protocol defines all files to be in "binary" mode.
- There is no equivalent to python's "text" mode.
-
- @param path: the requested path (relative or absolute) of the file
- to be opened.
- @type path: str
- @param flags: flags or'd together from the C{os} module indicating the
- requested mode for opening the file.
- @type flags: int
- @param attr: requested attributes of the file if it is newly created.
- @type attr: L{SFTPAttributes}
- @return: a new L{SFTPHandle} I{or error code}.
- @rtype L{SFTPHandle}
- """
- return SFTP_OP_UNSUPPORTED
-
- def list_folder(self, path):
- """
- Return a list of files within a given folder. The C{path} will use
- posix notation (C{"/"} separates folder names) and may be an absolute
- or relative path.
-
- The list of files is expected to be a list of L{SFTPAttributes}
- objects, which are similar in structure to the objects returned by
- C{os.stat}. In addition, each object should have its C{filename}
- field filled in, since this is important to a directory listing and
- not normally present in C{os.stat} results. The method
- L{SFTPAttributes.from_stat} will usually do what you want.
-
- In case of an error, you should return one of the C{SFTP_*} error
- codes, such as L{SFTP_PERMISSION_DENIED}.
-
- @param path: the requested path (relative or absolute) to be listed.
- @type path: str
- @return: a list of the files in the given folder, using
- L{SFTPAttributes} objects.
- @rtype: list of L{SFTPAttributes} I{or error code}
-
- @note: You should normalize the given C{path} first (see the
- C{os.path} module) and check appropriate permissions before returning
- the list of files. Be careful of malicious clients attempting to use
- relative paths to escape restricted folders, if you're doing a direct
- translation from the SFTP server path to your local filesystem.
- """
- return SFTP_OP_UNSUPPORTED
-
- def stat(self, path):
- """
- Return an L{SFTPAttributes} object for a path on the server, or an
- error code. If your server supports symbolic links (also known as
- "aliases"), you should follow them. (L{lstat} is the corresponding
- call that doesn't follow symlinks/aliases.)
-
- @param path: the requested path (relative or absolute) to fetch
- file statistics for.
- @type path: str
- @return: an attributes object for the given file, or an SFTP error
- code (like L{SFTP_PERMISSION_DENIED}).
- @rtype: L{SFTPAttributes} I{or error code}
- """
- return SFTP_OP_UNSUPPORTED
-
- def lstat(self, path):
- """
- Return an L{SFTPAttributes} object for a path on the server, or an
- error code. If your server supports symbolic links (also known as
- "aliases"), you should I{not} follow them -- instead, you should
- return data on the symlink or alias itself. (L{stat} is the
- corresponding call that follows symlinks/aliases.)
-
- @param path: the requested path (relative or absolute) to fetch
- file statistics for.
- @type path: str
- @return: an attributes object for the given file, or an SFTP error
- code (like L{SFTP_PERMISSION_DENIED}).
- @rtype: L{SFTPAttributes} I{or error code}
- """
- return SFTP_OP_UNSUPPORTED
-
- def remove(self, path):
- """
- Delete a file, if possible.
-
- @param path: the requested path (relative or absolute) of the file
- to delete.
- @type path: str
- @return: an SFTP error code like L{SFTP_OK}.
- @rtype: int
- """
- return SFTP_OP_UNSUPPORTED
-
- def rename(self, oldpath, newpath):
- """
- Rename (or move) a file. The SFTP specification implies that this
- method can be used to move an existing file into a different folder,
- and since there's no other (easy) way to move files via SFTP, it's
- probably a good idea to implement "move" in this method too, even for
- files that cross disk partition boundaries, if at all possible.
-
- @note: You should return an error if a file with the same name as
- C{newpath} already exists. (The rename operation should be
- non-desctructive.)
-
- @param oldpath: the requested path (relative or absolute) of the
- existing file.
- @type oldpath: str
- @param newpath: the requested new path of the file.
- @type newpath: str
- @return: an SFTP error code like L{SFTP_OK}.
- @rtype: int
- """
- return SFTP_OP_UNSUPPORTED
-
- def mkdir(self, path, attr):
- """
- Create a new directory with the given attributes. The C{attr}
- object may be considered a "hint" and ignored.
-
- The C{attr} object will contain only those fields provided by the
- client in its request, so you should use C{hasattr} to check for
- the presense of fields before using them. In some cases, the C{attr}
- object may be completely empty.
-
- @param path: requested path (relative or absolute) of the new
- folder.
- @type path: str
- @param attr: requested attributes of the new folder.
- @type attr: L{SFTPAttributes}
- @return: an SFTP error code like L{SFTP_OK}.
- @rtype: int
- """
- return SFTP_OP_UNSUPPORTED
-
- def rmdir(self, path):
- """
- Remove a directory if it exists. The C{path} should refer to an
- existing, empty folder -- otherwise this method should return an
- error.
-
- @param path: requested path (relative or absolute) of the folder
- to remove.
- @type path: str
- @return: an SFTP error code like L{SFTP_OK}.
- @rtype: int
- """
- return SFTP_OP_UNSUPPORTED
-
- def chattr(self, path, attr):
- """
- Change the attributes of a file. The C{attr} object will contain
- only those fields provided by the client in its request, so you
- should check for the presence of fields before using them.
-
- @param path: requested path (relative or absolute) of the file to
- change.
- @type path: str
- @param attr: requested attributes to change on the file.
- @type attr: L{SFTPAttributes}
- @return: an error code like L{SFTP_OK}.
- @rtype: int
- """
- return SFTP_OP_UNSUPPORTED
-
- def canonicalize(self, path):
- """
- Return the canonical form of a path on the server. For example,
- if the server's home folder is C{/home/foo}, the path
- C{"../betty"} would be canonicalized to C{"/home/betty"}. Note
- the obvious security issues: if you're serving files only from a
- specific folder, you probably don't want this method to reveal path
- names outside that folder.
-
- You may find the python methods in C{os.path} useful, especially
- C{os.path.normpath} and C{os.path.realpath}.
-
- The default implementation returns C{os.path.normpath('/' + path)}.
- """
- if os.path.isabs(path):
- out = os.path.normpath(path)
- else:
- out = os.path.normpath('/' + path)
- if sys.platform == 'win32':
- # on windows, normalize backslashes to sftp/posix format
- out = out.replace('\\', '/')
- return out
-
- def readlink(self, path):
- """
- Return the target of a symbolic link (or shortcut) on the server.
- If the specified path doesn't refer to a symbolic link, an error
- should be returned.
-
- @param path: path (relative or absolute) of the symbolic link.
- @type path: str
- @return: the target path of the symbolic link, or an error code like
- L{SFTP_NO_SUCH_FILE}.
- @rtype: str I{or error code}
- """
- return SFTP_OP_UNSUPPORTED
-
- def symlink(self, target_path, path):
- """
- Create a symbolic link on the server, as new pathname C{path},
- with C{target_path} as the target of the link.
-
- @param target_path: path (relative or absolute) of the target for
- this new symbolic link.
- @type target_path: str
- @param path: path (relative or absolute) of the symbolic link to
- create.
- @type path: str
- @return: an error code like C{SFTP_OK}.
- @rtype: int
- """
- return SFTP_OP_UNSUPPORTED