def session_login(self): """Authenticates the service on the device. Tries all the IP addrs listed in the san_ip parameter until a working one is found or the list is exhausted. """ try: self._get_session_key() self.get_firmware_version() if not self._array_name or self._array_name == 'unknown': self._array_name = self.get_serial_number() LOG.debug("Logged in to array %s at %s (session %s)", self._array_name, self._base_url, self._session_key) return except stx_exception.ConnectionError: not_responding = self._curr_ip_addr LOG.exception('session_login failed to connect to %s', self._curr_ip_addr) # Loop through the remaining management addresses # to find one that's up. for host in self._mgmt_ip_addrs: if host is not_responding: continue self._set_host(host) try: self._get_session_key() return except stx_exception.ConnectionError: LOG.error('Failed to connect to %s', self._curr_ip_addr) continue raise stx_exception.ConnectionError( message=_("Failed to log in to management controller"))
def _api_request(self, path, *args, **kargs): """Performs an HTTP request on the device, with locking. Raises a RequestError if the device returned but the status is not 0. The device error message will be used in the exception message. If the status is OK, returns the XML data for further processing. """ url = self._build_request_url(path, *args, **kargs) # Don't log the created URL since it may contain chap secret LOG.debug("Array Request path: %s, args: %s, kargs: %s (session %s)", path, args, strutils.mask_password(kargs), self._session_key) headers = {'dataType': 'api', 'sessionKey': self._session_key} try: xml = requests.get(url, headers=headers, verify=self.ssl_verify, timeout=60) tree = etree.XML(xml.text.encode('utf8')) except Exception as e: message = _("Exception handling URL %(url)s: %(msg)s") % { 'url': url, 'msg': e } raise stx_exception.ConnectionError(message=message) if path == "/show/volumecopy-status": return tree self._assert_response_ok(tree) return tree
def _get_session_key(self): """Retrieve a session key from the array.""" # TODO(alee): This appears to use md5 in a security related # context in providing a session key and hashing a login and # password. This should likely be replaced by a version that # does not use md5 here. self._session_key = None hash_ = "%s_%s" % (self._login, self._password) if six.PY3: hash_ = hash_.encode('utf-8') hash_ = hashlib.md5(hash_) # nosec digest = hash_.hexdigest() url = self._base_url + "/login/" + digest try: if self._protocol == 'https': xml = requests.get(url, verify=self.ssl_verify, timeout=30, auth=(self._login, self._password)) else: xml = requests.get(url, verify=self.ssl_verify, timeout=30) except requests.exceptions.RequestException: msg = _("Failed to obtain MC session key") LOG.exception(msg) raise stx_exception.ConnectionError(message=msg) self._get_auth_token(xml.text.encode('utf8')) LOG.debug("session key = %s", self._session_key) if self._session_key is None: raise stx_exception.AuthenticationError
def _get_session_key(self): """Retrieve a session key from the array.""" self._session_key = None hash_ = "%s_%s" % (self._login, self._password) if six.PY3: hash_ = hash_.encode('utf-8') hash_ = hashlib.md5(hash_) # nosec digest = hash_.hexdigest() url = self._base_url + "/login/" + digest try: if self._protocol == 'https': xml = requests.get(url, verify=self.ssl_verify, timeout=30, auth=(self._login, self._password)) else: xml = requests.get(url, verify=self.ssl_verify, timeout=30) except requests.exceptions.RequestException: msg = _("Failed to obtain MC session key") LOG.exception(msg) raise stx_exception.ConnectionError(message=msg) self._get_auth_token(xml.text.encode('utf8')) LOG.debug("session key = %s", self._session_key) if self._session_key is None: raise stx_exception.AuthenticationError
def _get_auth_token(self, xml): """Parse an XML authentication reply to extract the session key.""" self._session_key = None try: tree = etree.XML(xml) # The 'return-code' property is not valid in this context, so we # we check value of 'response-type-numeric' (0 => Success) rtn = tree.findtext(".//PROPERTY[@name='response-type-numeric']") session_key = tree.findtext(".//PROPERTY[@name='response']") if rtn == '0': self._session_key = session_key except Exception as e: msg = _("Cannot parse session key: %s") % e.msg raise stx_exception.ConnectionError(message=msg)
def client_login(self): try: self.client.login() except stx_exception.ConnectionError as ex: msg = _("Failed to connect to %(vendor_name)s Array %(host)s: " "%(err)s") % {'vendor_name': self.vendor_name, 'host': self.config.san_ip, 'err': six.text_type(ex)} LOG.error(msg) raise stx_exception.ConnectionError(message=msg) except stx_exception.AuthenticationError: msg = _("Failed to log on %s Array " "(invalid login?).") % self.vendor_name LOG.error(msg) raise stx_exception.AuthenticationError(message=msg)