diff --git a/proxmoxer/backends/base_ssh.py b/proxmoxer/backends/base_ssh.py index da624d9..10da5ac 100644 --- a/proxmoxer/backends/base_ssh.py +++ b/proxmoxer/backends/base_ssh.py @@ -9,10 +9,11 @@ class Response(object): - def __init__(self, content, status_code): + def __init__(self, content, status_code, reason): self.status_code = status_code self.content = content self.headers = {"content-type": "application/json"} + self.reason = reason class ProxmoxBaseSSHSession(object): @@ -40,19 +41,20 @@ def request(self, method, url, data=None, params=None, headers=None): data['filename'] = data['filename'].name data['tmpfilename'] = tmp_filename - translated_data = ' '.join(["-{0} {1}".format(k, v) for k, v in chain(data.items(), params.items())]) - full_cmd = 'pvesh {0}'.format(' '.join(filter(None, (cmd, url, translated_data)))) + translated_data = ' '.join(["-{0} {1}".format(k, v if not isinstance(v, str) or " " not in v else '"{}"'.format(v)) for k, v in chain(data.items(), params.items())]) + full_cmd = 'pvesh {0} --output-format json-pretty'.format(' '.join(filter(None, (cmd, url, translated_data)))) - stdout, stderr = self._exec(full_cmd) + stdout, stderr, error_code = self._exec(full_cmd) match = lambda s: re.match('\d\d\d [a-zA-Z]', s) # sometimes contains extra text like 'trying to acquire lock...OK' - status_code = next( - (int(s.split()[0]) for s in stderr.splitlines() if match(s)), - 500) - if stdout: - return Response(stdout, status_code) + + if (error_code == 0): + status_code=200 else: - return Response(stderr, status_code) + status_code = next( + (int(s.split()[0]) for s in stderr.splitlines() if match(s)), + 500) + return Response(stdout, status_code, stderr) def upload_file_obj(self, file_obj, remote_path): raise NotImplementedError() diff --git a/proxmoxer/backends/openssh.py b/proxmoxer/backends/openssh.py index 6c18373..4ac5553 100644 --- a/proxmoxer/backends/openssh.py +++ b/proxmoxer/backends/openssh.py @@ -40,7 +40,7 @@ def _exec(self, cmd): if self.sudo: cmd = "sudo " + cmd ret = self.ssh_client.run(cmd, forward_ssh_agent=self.forward_ssh_agent) - return ret.stdout, ret.stderr + return ret.stdout, ret.stderr, ret.returncode def upload_file_obj(self, file_obj, remote_path): self.ssh_client.scp((file_obj,), target=remote_path) diff --git a/proxmoxer/backends/ssh_paramiko.py b/proxmoxer/backends/ssh_paramiko.py index 482da55..7b0896f 100644 --- a/proxmoxer/backends/ssh_paramiko.py +++ b/proxmoxer/backends/ssh_paramiko.py @@ -56,9 +56,10 @@ def _exec(self, cmd): cmd = 'sudo ' + cmd session = self.ssh_client.get_transport().open_session() session.exec_command(cmd) - stdout = session.makefile('rb', -1).read().decode() - stderr = session.makefile_stderr('rb', -1).read().decode() - return stdout, stderr + error_code = session.recv_exit_status() + stdout = ''.join(session.makefile('r', -1)) + stderr = ''.join(session.makefile_stderr('r', -1)) + return stdout, stderr, error_code def upload_file_obj(self, file_obj, remote_path): sftp = self.ssh_client.open_sftp() diff --git a/proxmoxer/core.py b/proxmoxer/core.py index 43c3a06..b2c9b49 100644 --- a/proxmoxer/core.py +++ b/proxmoxer/core.py @@ -42,7 +42,16 @@ def url_join(self, base, *args): class ResourceException(Exception): - pass + def __init__(self, status_code, status_message, content, reason): + self.status_code = status_code + self.status_message = status_message + self.content = content + self.reason = reason.strip() + super(ResourceException, self).__init__(self.__repr__()) + + def __repr__(self): + return "{0} {1}: {2}, Content:{3}".format( + self.status_code, self.status_message, self.reason, self.content) class ProxmoxResource(ProxmoxResourceBase): @@ -75,8 +84,7 @@ def _request(self, method, data=None, params=None): logger.debug('Status code: %s, output: %s', resp.status_code, resp.content) if resp.status_code >= 400: - raise ResourceException("{0} {1}: {2}".format(resp.status_code, httplib.responses[resp.status_code], - resp.content)) + raise ResourceException(resp.status_code, httplib.responses[resp.status_code], resp.content, resp.reason) elif 200 <= resp.status_code <= 299: return self._store["serializer"].loads(resp)