def test_deployment_check_connect_failed(self, mock_clients_services): sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/", "admin", "adminpass").to_dict() deployment = {"admin": sample_credential} refused = keystone_exceptions.ConnectionRefused() mock_clients_services.side_effect = refused self.assertRaises(keystone_exceptions.ConnectionRefused, api.Deployment.check, deployment)
def test_deployment_check_connect_failed(self, mock_deployment_get, mock_clients_services): deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42" sample_endpoint = objects.Endpoint("http://192.168.1.1:5000/v2.0/", "admin", "adminpass").to_dict() mock_deployment_get.return_value = {"admin": sample_endpoint} refused = keystone_exceptions.ConnectionRefused() mock_clients_services.side_effect = refused self.assertEqual(self.deployment.check(deployment_id), 1)
def test_deployment_check_raise(self, mock_deployment_get, mock_deployment_check): deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42" sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/", "admin", "adminpass").to_dict() sample_credential["not-exist-key"] = "error" mock_deployment_get.return_value = {"admin": sample_credential} refused = keystone_exceptions.ConnectionRefused() mock_deployment_check.side_effect = refused self.assertEqual(self.deployment.check(deployment_id), 1)
def a(a): if a == 1: raise keystone_exc.Unauthorized() if a == 2: raise keystone_exc.AuthorizationFailure() if a == 3: raise keystone_exc.ConnectionRefused() return a
def _send_request(self, url, method, redirect, **kwargs): # NOTE(jamielennox): We handle redirection manually because the # requests lib follows some browser patterns where it will redirect # POSTs as GETs for certain statuses which is not want we want for an # API. See: https://en.wikipedia.org/wiki/Post/Redirect/Get try: resp = self.session.request(method, url, **kwargs) except requests.exceptions.SSLError: msg = 'SSL exception connecting to %s' % url raise exceptions.SSLError(msg) except requests.exceptions.Timeout: msg = 'Request to %s timed out' % url raise exceptions.RequestTimeout(msg) except requests.exceptions.ConnectionError: msg = 'Unable to establish connection to %s' % url raise exceptions.ConnectionRefused(msg) _logger.debug('RESP: [%s] %s\nRESP BODY: %s\n', resp.status_code, resp.headers, resp.text) if resp.status_code in self.REDIRECT_STATUSES: # be careful here in python True == 1 and False == 0 if isinstance(redirect, bool): redirect_allowed = redirect else: redirect -= 1 redirect_allowed = redirect >= 0 if not redirect_allowed: return resp try: location = resp.headers['location'] except KeyError: _logger.warn( "Failed to redirect request to %s as new " "location was not provided.", resp.url) else: new_resp = self._send_request(location, method, redirect, **kwargs) if not isinstance(new_resp.history, list): new_resp.history = list(new_resp.history) new_resp.history.insert(0, resp) resp = new_resp return resp
def _send_request(self, url, method, redirect, log, logger, connect_retries, connect_retry_delay=0.5, **kwargs): # NOTE(jamielennox): We handle redirection manually because the # requests lib follows some browser patterns where it will redirect # POSTs as GETs for certain statuses which is not want we want for an # API. See: https://en.wikipedia.org/wiki/Post/Redirect/Get # NOTE(jamielennox): The interaction between retries and redirects are # handled naively. We will attempt only a maximum number of retries and # redirects rather than per request limits. Otherwise the extreme case # could be redirects * retries requests. This will be sufficient in # most cases and can be fixed properly if there's ever a need. try: try: resp = self.session.request(method, url, **kwargs) except requests.exceptions.SSLError as e: msg = _('SSL exception connecting to %(url)s: ' '%(error)s') % { 'url': url, 'error': e } raise exceptions.SSLError(msg) except requests.exceptions.Timeout: msg = _('Request to %s timed out') % url raise exceptions.RequestTimeout(msg) except requests.exceptions.ConnectionError: msg = _('Unable to establish connection to %s') % url raise exceptions.ConnectionRefused(msg) except (exceptions.RequestTimeout, exceptions.ConnectionRefused) as e: if connect_retries <= 0: raise logger.info(_LI('Failure: %(e)s. Retrying in %(delay).1fs.'), { 'e': e, 'delay': connect_retry_delay }) time.sleep(connect_retry_delay) return self._send_request(url, method, redirect, log, logger, connect_retries=connect_retries - 1, connect_retry_delay=connect_retry_delay * 2, **kwargs) if log: self._http_log_response(resp, logger) if resp.status_code in self._REDIRECT_STATUSES: # be careful here in python True == 1 and False == 0 if isinstance(redirect, bool): redirect_allowed = redirect else: redirect -= 1 redirect_allowed = redirect >= 0 if not redirect_allowed: return resp try: location = resp.headers['location'] except KeyError: logger.warning( _LW("Failed to redirect request to %s as new " "location was not provided."), resp.url) else: # NOTE(jamielennox): We don't pass through connect_retry_delay. # This request actually worked so we can reset the delay count. new_resp = self._send_request(location, method, redirect, log, logger, connect_retries=connect_retries, **kwargs) if not isinstance(new_resp.history, list): new_resp.history = list(new_resp.history) new_resp.history.insert(0, resp) resp = new_resp return resp
class ShellTest(utils.TestCase): FAKE_ENV = { 'OS_USERNAME': '******', 'OS_PASSWORD': '******', 'OS_TENANT_NAME': 'tenant_name', 'OS_AUTH_URL': 'http://no.where/v2.0', } # Patch os.environ to avoid required auth info. def make_env(self, exclude=None, include=None): env = dict((k, v) for k, v in self.FAKE_ENV.items() if k != exclude) env.update(include or {}) self.useFixture(fixtures.MonkeyPatch('os.environ', env)) def setUp(self): super(ShellTest, self).setUp() for var in self.FAKE_ENV: self.useFixture( fixtures.EnvironmentVariable(var, self.FAKE_ENV[var])) def shell(self, argstr): orig = sys.stdout try: sys.stdout = moves.StringIO() _shell = shell.OpenStackCinderShell() _shell.main(argstr.split()) except SystemExit: exc_type, exc_value, exc_traceback = sys.exc_info() self.assertEqual(0, exc_value.code) finally: out = sys.stdout.getvalue() sys.stdout.close() sys.stdout = orig return out def test_help_unknown_command(self): self.assertRaises(exceptions.CommandError, self.shell, 'help foofoo') def test_help(self): required = [ '.*?^usage: ', '.*?(?m)^\s+create\s+Creates a volume.', '.*?(?m)^Run "cinder help SUBCOMMAND" for help on a subcommand.', ] help_text = self.shell('help') for r in required: self.assertThat(help_text, matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) def test_help_on_subcommand(self): required = [ '.*?^usage: cinder list', '.*?(?m)^Lists all volumes.', ] help_text = self.shell('help list') for r in required: self.assertThat(help_text, matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) def register_keystone_auth_fixture(self, mocker, url): mocker.register_uri('GET', url, text=keystone_client.keystone_request_callback) @requests_mock.Mocker() def test_version_discovery(self, mocker): _shell = shell.OpenStackCinderShell() os_auth_url = "https://WrongDiscoveryResponse.discovery.com:35357/v2.0" self.register_keystone_auth_fixture(mocker, os_auth_url) self.assertRaises(DiscoveryFailure, _shell._discover_auth_versions, None, auth_url=os_auth_url) os_auth_url = "https://DiscoveryNotSupported.discovery.com:35357/v2.0" self.register_keystone_auth_fixture(mocker, os_auth_url) v2_url, v3_url = _shell._discover_auth_versions(None, auth_url=os_auth_url) self.assertEqual(v2_url, os_auth_url, "Expected v2 url") self.assertIsNone(v3_url, "Expected no v3 url") os_auth_url = "https://DiscoveryNotSupported.discovery.com:35357/v3.0" self.register_keystone_auth_fixture(mocker, os_auth_url) v2_url, v3_url = _shell._discover_auth_versions(None, auth_url=os_auth_url) self.assertEqual(v3_url, os_auth_url, "Expected v3 url") self.assertIsNone(v2_url, "Expected no v2 url") @requests_mock.Mocker() def list_volumes_on_service(self, count, mocker): os_auth_url = "http://multiple.service.names/v2.0" mocker.register_uri('POST', os_auth_url + "/tokens", text=keystone_client.keystone_request_callback) mocker.register_uri('GET', "http://cinder%i.api.com/v2/volumes/detail" % count, text='{"volumes": []}') self.make_env(include={ 'OS_AUTH_URL': os_auth_url, 'CINDER_SERVICE_NAME': 'cinder%i' % count }) _shell = shell.OpenStackCinderShell() _shell.main(['list']) def test_cinder_service_name(self): # Failing with 'No mock address' means we are not # choosing the correct endpoint for count in range(1, 4): self.list_volumes_on_service(count) @mock.patch('keystoneclient.adapter.Adapter.get_token', side_effect=ks_exc.ConnectionRefused()) @mock.patch('keystoneclient.discover.Discover', side_effect=ks_exc.ConnectionRefused()) @mock.patch('sys.stdin', side_effect=mock.MagicMock) @mock.patch('getpass.getpass', return_value='password') def test_password_prompted(self, mock_getpass, mock_stdin, mock_discover, mock_token): self.make_env(exclude='OS_PASSWORD') _shell = shell.OpenStackCinderShell() self.assertRaises(ks_exc.ConnectionRefused, _shell.main, ['list']) mock_getpass.assert_called_with('OS Password: '******'fake' auth instead of keystone # and the auth plugin will provide the auth url self.make_env(exclude="OS_AUTH_URL", include={'OS_AUTH_SYSTEM': 'fake'}) # This should fail as we have not setup a mock response for 'list', # however auth should have been called _shell = shell.OpenStackCinderShell() self.assertRaises(KeyError, _shell.main, ['list']) headers = requested_headers(_shell.cs) token_url = _shell.cs.client.auth_url + "/tokens" self.assertEqual(non_keystone_auth_url + "/tokens", token_url) mock_request.assert_any_call("POST", token_url, headers=headers, data='{"fake": "me"}', allow_redirects=True, **self.TEST_REQUEST_BASE) @mock.patch.object(cinderclient.client.HTTPClient, 'authenticate', side_effect=exceptions.Unauthorized('No')) # Easiest way to make cinderclient use httpclient is a None session @mock.patch.object(cinderclient.shell.OpenStackCinderShell, '_get_keystone_session', return_value=None) def test_http_client_insecure(self, mock_authenticate, mock_session): self.make_env(include={'CINDERCLIENT_INSECURE': True}) _shell = shell.OpenStackCinderShell() # This "fails" but instantiates the client. self.assertRaises(exceptions.CommandError, _shell.main, ['list']) self.assertEqual(False, _shell.cs.client.verify_cert)