diff --git a/heat/common/heat_keystoneclient.py b/heat/common/heat_keystoneclient.py index 737a2529b..978b3ce90 100644 --- a/heat/common/heat_keystoneclient.py +++ b/heat/common/heat_keystoneclient.py @@ -154,3 +154,7 @@ class KeystoneClient(object): def url_for(self, **kwargs): return self.client.service_catalog.url_for(**kwargs) + + @property + def auth_token(self): + return self.client.auth_token diff --git a/heat/engine/clients.py b/heat/engine/clients.py index 22301d5ab..05cbcaf7c 100644 --- a/heat/engine/clients.py +++ b/heat/engine/clients.py @@ -61,6 +61,12 @@ class OpenStackClients(object): self._quantum = None self._cinder = None + @property + def auth_token(self): + # if there is no auth token in the context + # attempt to get one using the context username and password + return self.context.auth_token or self.keystone().auth_token + def keystone(self): if self._keystone: return self._keystone @@ -76,28 +82,23 @@ class OpenStackClients(object): return self._nova[service_type] con = self.context + if self.auth_token is None: + logger.error("Nova connection failed, no auth_token!") + return None + args = { 'project_id': con.tenant, 'auth_url': con.auth_url, 'service_type': service_type, + 'username': None, + 'api_key': None } - if con.password is not None: - args['username'] = con.username - args['api_key'] = con.password - elif con.auth_token is not None: - args['username'] = None - args['api_key'] = None - else: - logger.error("Nova connection failed, no password or auth_token!") - return None - client = novaclient.Client(1.1, **args) - if con.password is None and con.auth_token is not None: - management_url = self.url_for(service_type=service_type) - client.client.auth_token = con.auth_token - client.client.management_url = management_url + management_url = self.url_for(service_type=service_type) + client.client.auth_token = self.auth_token + client.client.management_url = management_url self._nova[service_type] = client return client @@ -109,24 +110,19 @@ class OpenStackClients(object): return self._swift con = self.context + if self.auth_token is None: + logger.error("Swift connection failed, no auth_token!") + return None + args = { 'auth_version': '2.0', 'tenant_name': con.tenant, - 'user': con.username + 'user': con.username, + 'key': None, + 'authurl': None, + 'preauthtoken': self.auth_token, + 'preauthurl': self.url_for(service_type='object-store') } - - if con.password is not None: - args['key'] = con.password - args['authurl'] = con.auth_url - elif con.auth_token is not None: - args['key'] = None - args['authurl'] = None - args['preauthtoken'] = con.auth_token - args['preauthurl'] = self.url_for(service_type='object-store') - else: - logger.error("Swift connection failed, no password or " + - "auth_token!") - return None self._swift = swiftclient.Connection(**args) return self._swift @@ -134,28 +130,20 @@ class OpenStackClients(object): if quantumclient is None: return None if self._quantum: - logger.debug('using existing _quantum') return self._quantum con = self.context + if self.auth_token is None: + logger.error("Quantum connection failed, no auth_token!") + return None + args = { 'auth_url': con.auth_url, 'service_type': 'network', + 'token': self.auth_token, + 'endpoint_url': self.url_for(service_type='network') } - if con.password is not None: - args['username'] = con.username - args['password'] = con.password - args['tenant_name'] = con.tenant - elif con.auth_token is not None: - args['token'] = con.auth_token - args['endpoint_url'] = self.url_for(service_type='network') - else: - logger.error("Quantum connection failed, " - "no password or auth_token!") - return None - logger.debug('quantum args %s', args) - self._quantum = quantumclient.Client(**args) return self._quantum @@ -167,29 +155,22 @@ class OpenStackClients(object): return self._cinder con = self.context + if self.auth_token is None: + logger.error("Cinder connection failed, no auth_token!") + return None + args = { 'service_type': 'volume', 'auth_url': con.auth_url, - 'project_id': con.tenant + 'project_id': con.tenant, + 'username': None, + 'api_key': None } - if con.password is not None: - args['username'] = con.username - args['api_key'] = con.password - elif con.auth_token is not None: - args['username'] = None - args['api_key'] = None - else: - logger.error("Cinder connection failed, " - "no password or auth_token!") - return None - logger.debug('cinder args %s', args) - self._cinder = cinderclient.Client('1', **args) - if con.password is None and con.auth_token is not None: - management_url = self.url_for(service_type='volume') - self._cinder.client.auth_token = con.auth_token - self._cinder.client.management_url = management_url + management_url = self.url_for(service_type='volume') + self._cinder.client.auth_token = self.auth_token + self._cinder.client.management_url = management_url return self._cinder diff --git a/heat/tests/fakes.py b/heat/tests/fakes.py index 17c754a54..6e77c7031 100644 --- a/heat/tests/fakes.py +++ b/heat/tests/fakes.py @@ -105,6 +105,7 @@ class FakeKeystoneClient(object): self.access = access self.secret = secret self.creds = None + self.auth_token = 'abcd1234' def create_stack_user(self, username, password=''): self.username = username diff --git a/heat/tests/test_parser.py b/heat/tests/test_parser.py index b4306bbc3..3c0e9acdb 100644 --- a/heat/tests/test_parser.py +++ b/heat/tests/test_parser.py @@ -26,6 +26,7 @@ from heat.engine import parameters from heat.engine import scheduler from heat.engine import template +from heat.tests.fakes import FakeKeystoneClient from heat.tests.common import HeatTestCase from heat.tests.utils import dummy_context from heat.tests.utils import setup_dummy_db @@ -532,6 +533,18 @@ class StackTest(HeatTestCase): self.assertEqual(stack.state, (None, None)) self.assertEqual(stack.status_reason, '') + def test_no_auth_token(self): + ctx = dummy_context() + ctx.auth_token = None + self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') + clients.OpenStackClients.keystone().AndReturn(FakeKeystoneClient()) + + self.m.ReplayAll() + stack = parser.Stack(ctx, 'test_stack', parser.Template({})) + self.assertEqual('abcd1234', stack.clients.auth_token) + + self.m.VerifyAll() + def test_state(self): stack = parser.Stack(self.ctx, 'test_stack', parser.Template({}), action=parser.Stack.CREATE, diff --git a/heat/tests/test_quantum.py b/heat/tests/test_quantum.py index ee5a6a3c2..de93843e6 100644 --- a/heat/tests/test_quantum.py +++ b/heat/tests/test_quantum.py @@ -15,6 +15,7 @@ from testtools import skipIf +from heat.engine import clients from heat.common import exception from heat.common import template_format from heat.engine import properties @@ -26,6 +27,7 @@ from heat.engine.resources.quantum import router from heat.engine.resources.quantum.quantum import QuantumResource as qr from heat.openstack.common.importutils import try_import from heat.tests.common import HeatTestCase +from heat.tests import fakes from heat.tests import utils from heat.tests.utils import setup_dummy_db from heat.tests.utils import parse_stack @@ -211,6 +213,7 @@ class QuantumNetTest(HeatTestCase): self.m.StubOutWithMock(quantumclient.Client, 'create_network') self.m.StubOutWithMock(quantumclient.Client, 'delete_network') self.m.StubOutWithMock(quantumclient.Client, 'show_network') + self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') setup_dummy_db() def create_net(self, t, stack, resource_name): @@ -220,6 +223,8 @@ class QuantumNetTest(HeatTestCase): return rsrc def test_net(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) quantumclient.Client.create_network({ 'network': {'name': u'the_network', 'admin_state_up': True} }).AndReturn({"network": { @@ -342,6 +347,7 @@ class QuantumSubnetTest(HeatTestCase): self.m.StubOutWithMock(quantumclient.Client, 'create_subnet') self.m.StubOutWithMock(quantumclient.Client, 'delete_subnet') self.m.StubOutWithMock(quantumclient.Client, 'show_subnet') + self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') setup_dummy_db() def create_subnet(self, t, stack, resource_name): @@ -353,6 +359,8 @@ class QuantumSubnetTest(HeatTestCase): def test_subnet(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) quantumclient.Client.create_subnet({ 'subnet': { 'name': utils.PhysName('test_stack', 'test_subnet'), @@ -447,6 +455,8 @@ class QuantumSubnetTest(HeatTestCase): def test_subnet_disable_dhcp(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) quantumclient.Client.create_subnet({ 'subnet': { 'name': utils.PhysName('test_stack', 'test_subnet'), @@ -525,6 +535,7 @@ class QuantumRouterTest(HeatTestCase): self.m.StubOutWithMock(quantumclient.Client, 'remove_interface_router') self.m.StubOutWithMock(quantumclient.Client, 'add_gateway_router') self.m.StubOutWithMock(quantumclient.Client, 'remove_gateway_router') + self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') setup_dummy_db() def create_router(self, t, stack, resource_name): @@ -554,6 +565,8 @@ class QuantumRouterTest(HeatTestCase): return rsrc def test_router(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) quantumclient.Client.create_router({ 'router': { 'name': utils.PhysName('test_stack', 'router'), @@ -659,6 +672,8 @@ class QuantumRouterTest(HeatTestCase): self.m.VerifyAll() def test_router_interface(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) quantumclient.Client.add_interface_router( '3e46229d-8fce-4733-819a-b5fe630550f8', {'subnet_id': '91e47a57-7508-46fe-afc9-fc454e8580e1'} @@ -687,6 +702,8 @@ class QuantumRouterTest(HeatTestCase): self.m.VerifyAll() def test_gateway_router(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) quantumclient.Client.add_gateway_router( '3e46229d-8fce-4733-819a-b5fe630550f8', {'network_id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'} @@ -725,10 +742,13 @@ class QuantumFloatingIPTest(HeatTestCase): self.m.StubOutWithMock(quantumclient.Client, 'create_port') self.m.StubOutWithMock(quantumclient.Client, 'delete_port') self.m.StubOutWithMock(quantumclient.Client, 'show_port') + self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') setup_dummy_db() def test_floating_ip(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) quantumclient.Client.create_floatingip({ 'floatingip': {'floating_network_id': u'abcd1234'} }).AndReturn({'floatingip': { @@ -789,6 +809,8 @@ class QuantumFloatingIPTest(HeatTestCase): def test_port(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) quantumclient.Client.create_port({'port': { 'network_id': u'xyz1234', 'fixed_ips': [ @@ -853,6 +875,8 @@ class QuantumFloatingIPTest(HeatTestCase): def test_floatip_port(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) quantumclient.Client.create_floatingip({ 'floatingip': {'floating_network_id': u'abcd1234'} }).AndReturn({'floatingip': { diff --git a/heat/tests/test_s3.py b/heat/tests/test_s3.py index 40f5e764a..2b93c3e85 100644 --- a/heat/tests/test_s3.py +++ b/heat/tests/test_s3.py @@ -20,9 +20,11 @@ from heat.common import template_format from heat.openstack.common.importutils import try_import from heat.engine.resources import s3 from heat.engine import resource +from heat.engine import clients from heat.engine import scheduler from heat.tests.common import HeatTestCase from heat.tests import utils +from heat.tests import fakes from heat.tests.utils import setup_dummy_db from heat.tests.utils import parse_stack @@ -63,6 +65,7 @@ class s3Test(HeatTestCase): self.m.StubOutWithMock(swiftclient.Connection, 'put_container') self.m.StubOutWithMock(swiftclient.Connection, 'delete_container') self.m.StubOutWithMock(swiftclient.Connection, 'get_auth') + self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') setup_dummy_db() @@ -75,6 +78,8 @@ class s3Test(HeatTestCase): return rsrc def test_attributes(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -111,6 +116,8 @@ class s3Test(HeatTestCase): self.m.VerifyAll() def test_public_read(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( utils.PhysName('test_stack', 'test_resource'), @@ -129,6 +136,8 @@ class s3Test(HeatTestCase): self.m.VerifyAll() def test_public_read_write(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -147,6 +156,8 @@ class s3Test(HeatTestCase): self.m.VerifyAll() def test_authenticated_read(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -164,6 +175,8 @@ class s3Test(HeatTestCase): self.m.VerifyAll() def test_website(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -181,6 +194,8 @@ class s3Test(HeatTestCase): self.m.VerifyAll() def test_delete_exception(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -199,6 +214,8 @@ class s3Test(HeatTestCase): def test_delete_retain(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) # first run, with retain policy swiftclient.Connection.put_container( utils.PhysName('test_stack', 'test_resource'), diff --git a/heat/tests/test_security_group.py b/heat/tests/test_security_group.py index 3097405b6..0d395a0ac 100644 --- a/heat/tests/test_security_group.py +++ b/heat/tests/test_security_group.py @@ -19,6 +19,7 @@ from heat.common import template_format from heat.engine import parser from heat.engine import resource from heat.tests.common import HeatTestCase +from heat.tests.fakes import FakeKeystoneClient from heat.tests.utils import dummy_context from heat.tests.utils import setup_dummy_db from heat.tests.v1_1 import fakes @@ -87,6 +88,7 @@ Resources: super(SecurityGroupTest, self).setUp() self.fc = fakes.FakeClient() self.m.StubOutWithMock(clients.OpenStackClients, 'nova') + self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') self.m.StubOutWithMock(nova_sgr.SecurityGroupRuleManager, 'create') self.m.StubOutWithMock(nova_sgr.SecurityGroupRuleManager, 'delete') self.m.StubOutWithMock(nova_sg.SecurityGroupManager, 'create') @@ -275,6 +277,8 @@ Resources: @stack_delete_after def test_security_group_quantum(self): #create script + clients.OpenStackClients.keystone().AndReturn( + FakeKeystoneClient()) sg_name = utils.PhysName('test_stack', 'the_sg') quantumclient.Client.create_security_group({ 'security_group': { @@ -415,6 +419,8 @@ Resources: @stack_delete_after def test_security_group_quantum_exception(self): #create script + clients.OpenStackClients.keystone().AndReturn( + FakeKeystoneClient()) sg_name = utils.PhysName('test_stack', 'the_sg') quantumclient.Client.create_security_group({ 'security_group': { diff --git a/heat/tests/test_swift.py b/heat/tests/test_swift.py index 74ad7db6a..7d5b587d5 100644 --- a/heat/tests/test_swift.py +++ b/heat/tests/test_swift.py @@ -20,9 +20,11 @@ from testtools import skipIf from heat.common import template_format from heat.openstack.common.importutils import try_import from heat.engine.resources import swift +from heat.engine import clients from heat.engine import resource from heat.engine import scheduler from heat.tests.common import HeatTestCase +from heat.tests import fakes from heat.tests import utils from heat.tests.utils import setup_dummy_db from heat.tests.utils import parse_stack @@ -64,6 +66,7 @@ class swiftTest(HeatTestCase): self.m.StubOutWithMock(swiftclient.Connection, 'delete_container') self.m.StubOutWithMock(swiftclient.Connection, 'head_container') self.m.StubOutWithMock(swiftclient.Connection, 'get_auth') + self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') setup_dummy_db() @@ -114,6 +117,8 @@ class swiftTest(HeatTestCase): "x-container-bytes-used": "17680980", "content-type": "text/plain; charset=utf-8"} + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -155,6 +160,8 @@ class swiftTest(HeatTestCase): self.m.VerifyAll() def test_public_read(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -172,6 +179,8 @@ class swiftTest(HeatTestCase): self.m.VerifyAll() def test_public_read_write(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -190,6 +199,8 @@ class swiftTest(HeatTestCase): self.m.VerifyAll() def test_website(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -207,6 +218,8 @@ class swiftTest(HeatTestCase): self.m.VerifyAll() def test_delete_exception(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) container_name = utils.PhysName('test_stack', 'test_resource') swiftclient.Connection.put_container( container_name, @@ -225,6 +238,8 @@ class swiftTest(HeatTestCase): def test_delete_retain(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) # first run, with retain policy swiftclient.Connection.put_container( utils.PhysName('test_stack', 'test_resource'), diff --git a/heat/tests/test_vpc.py b/heat/tests/test_vpc.py index 6e8635742..641f85cc5 100644 --- a/heat/tests/test_vpc.py +++ b/heat/tests/test_vpc.py @@ -17,8 +17,10 @@ from testtools import skipIf from heat.common import exception from heat.common import template_format from heat.engine import parser +from heat.engine import clients from heat.engine import resource from heat.tests.common import HeatTestCase +from heat.tests import fakes from heat.tests import utils from heat.tests.utils import dummy_context from heat.tests.utils import setup_dummy_db @@ -60,6 +62,7 @@ class VPCTestBase(HeatTestCase): quantumclient.Client, 'create_security_group_rule') self.m.StubOutWithMock( quantumclient.Client, 'delete_security_group_rule') + self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') def create_stack(self, template): t = template_format.parse(template) @@ -74,6 +77,10 @@ class VPCTestBase(HeatTestCase): stack.store() return stack + def mock_keystone(self): + clients.OpenStackClients.keystone().AndReturn( + fakes.FakeKeystoneClient()) + def mock_create_network(self): self.vpc_name = utils.PhysName('test_stack', 'the_vpc') quantumclient.Client.create_network( @@ -331,6 +338,7 @@ Resources: ''' def test_vpc(self): + self.mock_keystone() self.mock_create_network() self.mock_delete_network() self.m.ReplayAll() @@ -362,6 +370,7 @@ Resources: ''' def test_subnet(self): + self.mock_keystone() self.mock_create_network() self.mock_create_subnet() self.mock_delete_subnet() @@ -538,6 +547,7 @@ Resources: quantumclient.Client.delete_port('dddd').AndReturn(None) def test_network_interface(self): + self.mock_keystone() self.mock_create_security_group() self.mock_create_network() self.mock_create_subnet() @@ -565,6 +575,7 @@ Resources: self.m.VerifyAll() def test_network_interface_no_groupset(self): + self.mock_keystone() self.mock_create_network() self.mock_create_subnet() self.mock_show_subnet() @@ -592,6 +603,7 @@ Resources: self.assertEquals(str(expected_exception), str(real_exception)) def test_network_interface_error_no_ref(self): + self.mock_keystone() self.mock_create_network() self.mock_create_subnet() self.mock_show_subnet() @@ -667,6 +679,7 @@ Resources: quantumclient.Client.remove_gateway_router('ffff').AndReturn(None) def test_internet_gateway(self): + self.mock_keystone() self.mock_create_internet_gateway() self.mock_create_network() self.mock_create_subnet() @@ -727,6 +740,7 @@ Resources: ''' def test_route_table(self): + self.mock_keystone() self.mock_create_network() self.mock_create_subnet() self.mock_create_route_table() diff --git a/heat/tests/utils.py b/heat/tests/utils.py index 72828c0bf..220ade0cc 100644 --- a/heat/tests/utils.py +++ b/heat/tests/utils.py @@ -102,7 +102,8 @@ def dummy_context(user='test_username', tenant_id='test_tenant_id', 'username': user, 'password': password, 'roles': roles, - 'auth_url': 'http://localhost:5000/v2.0' + 'auth_url': 'http://localhost:5000/v2.0', + 'auth_token': 'abcd1234' })