diff options
-rw-r--r-- | nova/virt/xenapi/vmops.py | 14 | ||||
-rwxr-xr-x | plugins/xenserver/xenapi/etc/xapi.d/plugins/agent | 95 |
2 files changed, 12 insertions, 97 deletions
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 206970c35..c10943aa1 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -220,6 +220,9 @@ class VMOps(object): dh = SimpleDH() args = {'id': transaction_id, 'pub': str(dh.get_public())} resp = self._make_agent_call('key_init', instance, '', args) + if resp is None: + # No response from the agent + return resp_dict = json.loads(resp) # Successful return code from key_init is 'D0' if resp_dict['returncode'] != 'D0': @@ -232,6 +235,9 @@ class VMOps(object): # Send the encrypted password args['enc_pass'] = enc_pass resp = self._make_agent_call('password', instance, '', args) + if resp is None: + # No response from the agent + return resp_dict = json.loads(resp) # Successful return code from password is '0' if resp_dict['returncode'] != '0': @@ -384,12 +390,16 @@ class VMOps(object): task = self._session.async_call_plugin(plugin, method, args) ret = self._session.wait_for_task(instance_id, task) except self.XenAPI.Failure, e: + ret = None err_trace = e.details[-1] err_msg = err_trace.splitlines()[-1] + strargs = str(args) if 'TIMEOUT:' in err_msg: - raise exception.TimeoutException(err_msg) + LOG.error(_('TIMEOUT: The call to %(method)s timed out. ' + 'VM id=%(instance_id)s; args=%(strargs)s') % locals()) else: - raise RuntimeError("%s" % e.details[-1]) + LOG.error(_('The call to %(method)s returned an error: %(e)s. ' + 'VM id=%(instance_id)s; args=%(strargs)s') % locals()) return ret def add_to_xenstore(self, vm, path, key, value): diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent index 82dd5466e..12c3a19c8 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent @@ -51,101 +51,6 @@ class TimeoutError(StandardError): pass -class SimpleDH(object): - """This class wraps all the functionality needed to implement - basic Diffie-Hellman-Merkle key exchange in Python. It features - intelligent defaults for the prime and base numbers needed for the - calculation, while allowing you to supply your own. It requires that - the openssl binary be installed on the system on which this is run, - as it uses that to handle the encryption and decryption. If openssl - is not available, a RuntimeError will be raised. - - Please note that nova already uses the M2Crypto library for most - cryptographic functions, and that it includes a Diffie-Hellman - implementation. However, that is a much more complex implementation, - and is not compatible with the DH algorithm that the agent uses. Hence - the need for this 'simple' version. - """ - def __init__(self, prime=None, base=None, secret=None): - """You can specify the values for prime and base if you wish; - otherwise, reasonable default values will be used. - """ - if prime is None: - self._prime = 162259276829213363391578010288127 - else: - self._prime = prime - if base is None: - self._base = 5 - else: - self._base = base - if secret is None: - self._secret = random.randint(5000, 15000) - else: - self._secret = secret - self._shared = self._public = None - - def get_public(self): - """Return the public key""" - self._public = (self._base ** self._secret) % self._prime - return self._public - - def compute_shared(self, other): - """Given the other end's public key, compute the - shared secret. - """ - self._shared = (other ** self._secret) % self._prime - return self._shared - - def _run_ssl(self, text, which): - """The encryption/decryption methods require running the openssl - installed on the system. This method abstracts out the common - code required. - """ - base_cmd = ("cat %(tmpfile)s | openssl enc -aes-128-cbc " - "-a -pass pass:%(shared)s -nosalt %(dec_flag)s") - if which.lower()[0] == "d": - dec_flag = " -d" - else: - dec_flag = "" - # Note: instead of using 'cat' and a tempfile, it is also - # possible to just 'echo' the value. However, we can not assume - # that the value is 'safe'; i.e., it may contain semi-colons, - # octothorpes, or other characters that would not be allowed - # in an 'echo' construct. - fd, tmpfile = tempfile.mkstemp() - os.close(fd) - file(tmpfile, "w").write(text) - shared = self._shared - cmd = base_cmd % locals() - try: - return _run_command(cmd) - except PluginError, e: - raise RuntimeError("OpenSSL error: %s" % e) - - def encrypt(self, text): - """Uses the shared key to encrypt the given text.""" - return self._run_ssl(text, "enc") - - def decrypt(self, text): - """Uses the shared key to decrypt the given text.""" - return self._run_ssl(text, "dec") - - -def _run_command(cmd): - """Abstracts out the basics of issuing system commands. If the command - returns anything in stderr, a PluginError is raised with that information. - Otherwise, the output from stdout is returned. - """ - pipe = subprocess.PIPE - proc = subprocess.Popen([cmd], shell=True, stdin=pipe, stdout=pipe, - stderr=pipe, close_fds=True) - proc.wait() - err = proc.stderr.read() - if err: - raise PluginError(err) - return proc.stdout.read() - - @jsonify def key_init(self, arg_dict): """Handles the Diffie-Hellman key exchange with the agent to |