def translate_exception(e, msg=None): """ In many cases, we should be able to roughly infer the exception cause from the error message -- this is centrally done in this method. If possible, it will return a new exception with a more concise error message and appropriate exception type. """ if not issubclass(e.__class__, se.SagaException): # we do not touch non-saga exceptions return e if not issubclass(e.__class__, se.NoSuccess): # this seems to have a specific cause already, leave it alone return e cmsg = e._plain_message if msg: cmsg = "%s (%s)" % (cmsg, msg) lmsg = cmsg.lower() if 'could not resolve hostname' in lmsg: e = se.BadParameter(cmsg) elif 'connection timed out' in lmsg: e = se.BadParameter(cmsg) elif 'connection refused' in lmsg: e = se.BadParameter(cmsg) elif 'auth' in lmsg: e = se.AuthorizationFailed(cmsg) elif 'pass' in lmsg: e = se.AuthenticationFailed(cmsg) elif 'ssh_exchange_identification' in lmsg: e = se.AuthenticationFailed( "too frequent login attempts, or sshd misconfiguration: %s" % cmsg) elif 'denied' in lmsg: e = se.PermissionDenied(cmsg) elif 'shared connection' in lmsg: e = se.NoSuccess("Insufficient system resources: %s" % cmsg) elif 'pty allocation' in lmsg: e = se.NoSuccess("Insufficient system resources: %s" % cmsg) elif 'Connection to master closed' in lmsg: e = se.NoSuccess( "Connection failed (insufficient system resources?): %s" % cmsg) return e
def _initialize(self, session): # make sure we have can access the key api = self.get_api() key = None pub = None pwd = None if api.attribute_exists(saga.context.USER_KEY): key = api.get_attribute(saga.context.USER_KEY) if api.attribute_exists(saga.context.USER_CERT): pub = api.get_attribute(saga.context.USER_CERT) if api.attribute_exists(saga.context.USER_PASS): pwd = api.get_attribute(saga.context.USER_PASS) # either user_key or user_cert should be specified (or both), # then we complement the other, and convert to/from private # from/to public keys if pub and not key: key = pub if not key: # nothing to do, really. This likely means that ssh setup is # done out-of-band. return # convert public key into private key if key.endswith('.pub'): if not pub: pub = key key = key[:-4] elif key.endswith('.pem'): if not pub: pub = key else: if not pub: pub = key + '.pub' # update the context with these setting api.set_attribute(saga.context.USER_KEY, key) api.set_attribute(saga.context.USER_CERT, pub) # the private and public keys must exist if not os.path.exists (key) or \ not os.path.isfile (key) : raise se.BadParameter("ssh key inaccessible: %s" % (key)) if not os.path.exists (pub) or \ not os.path.isfile (pub) : raise se.BadParameter("ssh public key inaccessible: %s" % (pub)) try: fh_key = open(key) except Exception as e: raise se.PermissionDenied("ssh key '%s' not readable: %s" % (key, e)) else: fh_key.close() try: fh_pub = open(pub) except Exception as e: raise se.PermissionDenied("ssh public key '%s' not readable: %s" % (pub, e)) else: fh_pub.close() import subprocess if not subprocess.call( ["sh", "-c", "grep ENCRYPTED %s > /dev/null" % key]): if pwd: if subprocess.call([ "sh", "-c", "ssh-keygen -y -f %s -P %s > /dev/null" % (key, pwd) ]): raise se.PermissionDenied( "ssh key '%s' is encrypted, incorrect password" % (key)) else: self._logger.error( "ssh key '%s' is encrypted, unknown password" % (key)) self._logger.info("init SSH context for key at '%s' done" % key)