| 157 | |
| 158 | |
| 159 | class SSHHTTPAdapter(BaseHTTPAdapter): |
| 160 | |
| 161 | __attrs__ = requests.adapters.HTTPAdapter.__attrs__ + [ |
| 162 | 'pools', 'timeout', 'ssh_client', 'ssh_params', 'max_pool_size' |
| 163 | ] |
| 164 | |
| 165 | def __init__(self, base_url, timeout=60, |
| 166 | pool_connections=constants.DEFAULT_NUM_POOLS, |
| 167 | max_pool_size=constants.DEFAULT_MAX_POOL_SIZE, |
| 168 | shell_out=False): |
| 169 | self.ssh_client = None |
| 170 | if not shell_out: |
| 171 | self._create_paramiko_client(base_url) |
| 172 | self._connect() |
| 173 | |
| 174 | self.ssh_host = base_url |
| 175 | if base_url.startswith('ssh://'): |
| 176 | self.ssh_host = base_url[len('ssh://'):] |
| 177 | |
| 178 | self.timeout = timeout |
| 179 | self.max_pool_size = max_pool_size |
| 180 | self.pools = RecentlyUsedContainer( |
| 181 | pool_connections, dispose_func=lambda p: p.close() |
| 182 | ) |
| 183 | super().__init__() |
| 184 | |
| 185 | def _create_paramiko_client(self, base_url): |
| 186 | logging.getLogger("paramiko").setLevel(logging.WARNING) |
| 187 | self.ssh_client = paramiko.SSHClient() |
| 188 | base_url = urllib.parse.urlparse(base_url) |
| 189 | self.ssh_params = { |
| 190 | "hostname": base_url.hostname, |
| 191 | "port": base_url.port, |
| 192 | "username": base_url.username |
| 193 | } |
| 194 | ssh_config_file = os.path.expanduser("~/.ssh/config") |
| 195 | if os.path.exists(ssh_config_file): |
| 196 | conf = paramiko.SSHConfig() |
| 197 | with open(ssh_config_file) as f: |
| 198 | conf.parse(f) |
| 199 | host_config = conf.lookup(base_url.hostname) |
| 200 | if 'proxycommand' in host_config: |
| 201 | self.ssh_params["sock"] = paramiko.ProxyCommand( |
| 202 | host_config['proxycommand'] |
| 203 | ) |
| 204 | if 'hostname' in host_config: |
| 205 | self.ssh_params['hostname'] = host_config['hostname'] |
| 206 | if base_url.port is None and 'port' in host_config: |
| 207 | self.ssh_params['port'] = host_config['port'] |
| 208 | if base_url.username is None and 'user' in host_config: |
| 209 | self.ssh_params['username'] = host_config['user'] |
| 210 | if 'identityfile' in host_config: |
| 211 | self.ssh_params['key_filename'] = host_config['identityfile'] |
| 212 | |
| 213 | self.ssh_client.load_system_host_keys() |
| 214 | self.ssh_client.set_missing_host_key_policy(paramiko.RejectPolicy()) |
| 215 | |
| 216 | def _connect(self): |