Add deployment check subcommand
* Check keystone endpoints and print user-friendly messages so the user can easily troubleshoot issues, * List all available services of your deployed OpenStack, * Refactoring of benchmark.engine.bind in order to avoid redundancy. Implements blueprint deployment-check-subcommand Change-Id: Iecfc2e4c093f567b56c3990c598326942c50e34a
This commit is contained in:
@@ -16,8 +16,6 @@
|
|||||||
import json
|
import json
|
||||||
import jsonschema
|
import jsonschema
|
||||||
|
|
||||||
from keystoneclient import exceptions as keystone_exceptions
|
|
||||||
|
|
||||||
from rally.benchmark import base
|
from rally.benchmark import base
|
||||||
from rally.benchmark import runner
|
from rally.benchmark import runner
|
||||||
from rally import consts
|
from rally import consts
|
||||||
@@ -161,18 +159,7 @@ class TestEngine(object):
|
|||||||
password=self.endpoint['password'],
|
password=self.endpoint['password'],
|
||||||
tenant_name=self.endpoint['tenant_name'],
|
tenant_name=self.endpoint['tenant_name'],
|
||||||
auth_url=self.endpoint['auth_url'])
|
auth_url=self.endpoint['auth_url'])
|
||||||
|
clients.get_verified_keystone_client()
|
||||||
try:
|
|
||||||
# Ensure that user is admin
|
|
||||||
roles = clients.get_keystone_client().auth_ref['user']['roles']
|
|
||||||
if not any("admin" == role['name'] for role in roles):
|
|
||||||
raise exceptions.InvalidAdminException(
|
|
||||||
username=self.endpoint["username"])
|
|
||||||
except keystone_exceptions.Unauthorized:
|
|
||||||
raise exceptions.InvalidEndpointsException()
|
|
||||||
except keystone_exceptions.AuthorizationFailure:
|
|
||||||
raise exceptions.HostUnreachableException(
|
|
||||||
url=self.endpoint['auth_url'])
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
|
@@ -31,6 +31,7 @@ from rally import exceptions
|
|||||||
from rally import fileutils
|
from rally import fileutils
|
||||||
from rally.openstack.common.gettextutils import _
|
from rally.openstack.common.gettextutils import _
|
||||||
from rally.orchestrator import api
|
from rally.orchestrator import api
|
||||||
|
from rally import osclients
|
||||||
from rally import processing
|
from rally import processing
|
||||||
|
|
||||||
|
|
||||||
@@ -145,6 +146,35 @@ class DeploymentCommands(object):
|
|||||||
table.add_row([endpoint.get(m, '') for m in headers])
|
table.add_row([endpoint.get(m, '') for m in headers])
|
||||||
print(table)
|
print(table)
|
||||||
|
|
||||||
|
@cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False,
|
||||||
|
help='UUID of a deployment.')
|
||||||
|
def check(self, deploy_id=None):
|
||||||
|
"""Check the deployment.
|
||||||
|
|
||||||
|
Check keystone authentication and list all available services.
|
||||||
|
|
||||||
|
:param deploy_id: a UUID of the deployment
|
||||||
|
"""
|
||||||
|
deploy_id = deploy_id or envutils.default_deployment_id()
|
||||||
|
headers = ['services', 'type', 'status']
|
||||||
|
table = prettytable.PrettyTable(headers)
|
||||||
|
try:
|
||||||
|
endpoint = db.deployment_get(deploy_id)['endpoint']
|
||||||
|
clients = osclients.Clients(username=endpoint['username'],
|
||||||
|
password=endpoint['password'],
|
||||||
|
tenant_name=endpoint['tenant_name'],
|
||||||
|
auth_url=endpoint['auth_url'])
|
||||||
|
client = clients.get_verified_keystone_client()
|
||||||
|
print("keystone endpoints are valid and following services are "
|
||||||
|
"available:")
|
||||||
|
for service in client.service_catalog.get_data():
|
||||||
|
table.add_row([service['name'], service['type'], 'Available'])
|
||||||
|
except exceptions.InvalidArgumentsException:
|
||||||
|
table.add_row(['keystone', 'identity', 'Error'])
|
||||||
|
print(_("Authentication Issues: %s.")
|
||||||
|
% sys.exc_info()[1])
|
||||||
|
print(table)
|
||||||
|
|
||||||
|
|
||||||
class TaskCommands(object):
|
class TaskCommands(object):
|
||||||
|
|
||||||
|
@@ -17,9 +17,12 @@ import urlparse
|
|||||||
|
|
||||||
from cinderclient import client as cinder
|
from cinderclient import client as cinder
|
||||||
import glanceclient as glance
|
import glanceclient as glance
|
||||||
|
from keystoneclient import exceptions as keystone_exceptions
|
||||||
from keystoneclient.v2_0 import client as keystone
|
from keystoneclient.v2_0 import client as keystone
|
||||||
from novaclient import client as nova
|
from novaclient import client as nova
|
||||||
|
|
||||||
|
from rally import exceptions
|
||||||
|
|
||||||
|
|
||||||
class Clients(object):
|
class Clients(object):
|
||||||
"""This class simplify and unify work with openstack python clients."""
|
"""This class simplify and unify work with openstack python clients."""
|
||||||
@@ -42,6 +45,25 @@ class Clients(object):
|
|||||||
self.cache["keystone"] = client
|
self.cache["keystone"] = client
|
||||||
return client
|
return client
|
||||||
|
|
||||||
|
def get_verified_keystone_client(self):
|
||||||
|
"""Ensure keystone endpoints are valid and then authenticate
|
||||||
|
|
||||||
|
:returns: Keystone Client
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Ensure that user is admin
|
||||||
|
client = self.get_keystone_client()
|
||||||
|
roles = client.auth_ref['user']['roles']
|
||||||
|
if not any('admin' == role['name'] for role in roles):
|
||||||
|
raise exceptions.InvalidAdminException(
|
||||||
|
username=self.kw['username'])
|
||||||
|
except keystone_exceptions.Unauthorized:
|
||||||
|
raise exceptions.InvalidEndpointsException()
|
||||||
|
except keystone_exceptions.AuthorizationFailure:
|
||||||
|
raise exceptions.HostUnreachableException(
|
||||||
|
url=self.kw['auth_url'])
|
||||||
|
return client
|
||||||
|
|
||||||
def get_nova_client(self, version='2'):
|
def get_nova_client(self, version='2'):
|
||||||
"""Returns nova client."""
|
"""Returns nova client."""
|
||||||
if "nova" in self.cache:
|
if "nova" in self.cache:
|
||||||
|
@@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from keystoneclient import exceptions as keystone_exceptions
|
|
||||||
|
|
||||||
from rally.benchmark import engine
|
from rally.benchmark import engine
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
@@ -122,34 +120,6 @@ class TestEngineTestCase(test.TestCase):
|
|||||||
with tester.bind(self.valid_endpoint):
|
with tester.bind(self.valid_endpoint):
|
||||||
self.assertEqual(tester.endpoint, self.valid_endpoint)
|
self.assertEqual(tester.endpoint, self.valid_endpoint)
|
||||||
|
|
||||||
@mock.patch("rally.benchmark.engine.osclients")
|
|
||||||
def test_bind_user_not_admin(self, mock_osclients):
|
|
||||||
mock_osclients.Clients.return_value = fakes.FakeClients()
|
|
||||||
mock_osclients.Clients.return_value.get_keystone_client(). \
|
|
||||||
auth_ref['user']['roles'] = [{'name': 'notadmin'}]
|
|
||||||
tester = engine.TestEngine(self.valid_test_config_continuous_times,
|
|
||||||
mock.MagicMock())
|
|
||||||
self.assertRaises(exceptions.InvalidAdminException,
|
|
||||||
tester.bind, self.valid_endpoint)
|
|
||||||
|
|
||||||
@mock.patch("rally.cmd.main.api.engine.osclients.Clients"
|
|
||||||
".get_keystone_client")
|
|
||||||
def test_bind_unauthorized_keystone(self, mock_osclients):
|
|
||||||
mock_osclients.side_effect = keystone_exceptions.Unauthorized
|
|
||||||
tester = engine.TestEngine(self.valid_test_config_continuous_times,
|
|
||||||
mock.MagicMock())
|
|
||||||
self.assertRaises(exceptions.InvalidEndpointsException,
|
|
||||||
tester.bind, self.valid_endpoint)
|
|
||||||
|
|
||||||
@mock.patch("rally.cmd.main.api.engine.osclients.Clients"
|
|
||||||
".get_keystone_client")
|
|
||||||
def test_bind_keystone_host_unreachable(self, mock_osclients):
|
|
||||||
mock_osclients.side_effect = keystone_exceptions.AuthorizationFailure
|
|
||||||
tester = engine.TestEngine(self.valid_test_config_continuous_times,
|
|
||||||
mock.MagicMock())
|
|
||||||
self.assertRaises(exceptions.HostUnreachableException,
|
|
||||||
tester.bind, self.valid_endpoint)
|
|
||||||
|
|
||||||
@mock.patch("rally.benchmark.runner.ScenarioRunner.run")
|
@mock.patch("rally.benchmark.runner.ScenarioRunner.run")
|
||||||
@mock.patch("rally.benchmark.utils.osclients")
|
@mock.patch("rally.benchmark.utils.osclients")
|
||||||
@mock.patch("rally.benchmark.engine.osclients")
|
@mock.patch("rally.benchmark.engine.osclients")
|
||||||
|
@@ -374,6 +374,9 @@ class FakeClients(object):
|
|||||||
self.keystone = FakeKeystoneClient()
|
self.keystone = FakeKeystoneClient()
|
||||||
return self.keystone
|
return self.keystone
|
||||||
|
|
||||||
|
def get_verified_keystone_client(self):
|
||||||
|
return self.get_keystone_client()
|
||||||
|
|
||||||
def get_nova_client(self):
|
def get_nova_client(self):
|
||||||
if self.nova is not None:
|
if self.nova is not None:
|
||||||
return self.nova
|
return self.nova
|
||||||
|
@@ -15,6 +15,9 @@
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from keystoneclient import exceptions as keystone_exceptions
|
||||||
|
|
||||||
|
from rally import exceptions
|
||||||
from rally import osclients
|
from rally import osclients
|
||||||
from tests import fakes
|
from tests import fakes
|
||||||
from tests import test
|
from tests import test
|
||||||
@@ -47,6 +50,28 @@ class OSClientsTestCase(test.TestCase):
|
|||||||
mock_keystone.Client.assert_called_once_with(**kwargs)
|
mock_keystone.Client.assert_called_once_with(**kwargs)
|
||||||
self.assertEqual(self.clients.cache["keystone"], fake_keystone)
|
self.assertEqual(self.clients.cache["keystone"], fake_keystone)
|
||||||
|
|
||||||
|
@mock.patch('rally.osclients.Clients.get_keystone_client')
|
||||||
|
def test_get_verified_keystone_client_user_not_admin(self, mock_keystone):
|
||||||
|
mock_keystone.return_value = fakes.FakeKeystoneClient()
|
||||||
|
mock_keystone.return_value.auth_ref['user']['roles'] = \
|
||||||
|
[{'name': 'notadmin'}]
|
||||||
|
self.assertRaises(exceptions.InvalidAdminException,
|
||||||
|
self.clients.get_verified_keystone_client)
|
||||||
|
|
||||||
|
@mock.patch('rally.osclients.Clients.get_keystone_client')
|
||||||
|
def test_get_verified_keystone_client_unauthorized(self, mock_keystone):
|
||||||
|
mock_keystone.return_value = fakes.FakeKeystoneClient()
|
||||||
|
mock_keystone.side_effect = keystone_exceptions.Unauthorized
|
||||||
|
self.assertRaises(exceptions.InvalidEndpointsException,
|
||||||
|
self.clients.get_verified_keystone_client)
|
||||||
|
|
||||||
|
@mock.patch('rally.osclients.Clients.get_keystone_client')
|
||||||
|
def test_get_verified_keystone_client_unreachable(self, mock_keystone):
|
||||||
|
mock_keystone.return_value = fakes.FakeKeystoneClient()
|
||||||
|
mock_keystone.side_effect = keystone_exceptions.AuthorizationFailure
|
||||||
|
self.assertRaises(exceptions.HostUnreachableException,
|
||||||
|
self.clients.get_verified_keystone_client)
|
||||||
|
|
||||||
def test_get_nova_client(self):
|
def test_get_nova_client(self):
|
||||||
with mock.patch('rally.osclients.nova') as mock_nova:
|
with mock.patch('rally.osclients.nova') as mock_nova:
|
||||||
fake_nova = fakes.FakeNovaClient()
|
fake_nova = fakes.FakeNovaClient()
|
||||||
|
Reference in New Issue
Block a user