]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Move client connection out of resources.py.
authorSteve Baker <sbaker@redhat.com>
Thu, 8 Nov 2012 02:49:19 +0000 (15:49 +1300)
committerSteve Baker <sbaker@redhat.com>
Thu, 8 Nov 2012 02:49:29 +0000 (15:49 +1300)
Client connection references are currently cached at the resource instance
level, which doesn't seem very useful.

This change moves the client connection and caching to clients.py, then puts a
Clients instance in a Stack. This means that (for example) all requests to nova
in one stack will come from the same client instance.

Change-Id: I22519f8ae4278ad128d3785d090294285f3a1b89

heat/engine/clients.py [new file with mode: 0644]
heat/engine/parser.py
heat/engine/resources/resource.py

diff --git a/heat/engine/clients.py b/heat/engine/clients.py
new file mode 100644 (file)
index 0000000..2ebf833
--- /dev/null
@@ -0,0 +1,191 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+
+from novaclient.v1_1 import client as nc
+from keystoneclient.v2_0 import client as kc
+
+# swiftclient not available in all distributions - make s3 an optional
+# feature
+try:
+    from swiftclient import client as swiftclient
+    swiftclient_present = True
+except ImportError:
+    swiftclient_present = False
+# quantumclient not available in all distributions - make quantum an optional
+# feature
+try:
+    from quantumclient.v2_0 import client as quantumclient
+    quantumclient_present = True
+except ImportError:
+    quantumclient_present = False
+
+from heat.openstack.common import log as logging
+
+logger = logging.getLogger('heat.engine.clients')
+
+
+class Clients(object):
+    '''
+    Convenience class to create and cache client instances.
+    '''
+
+    def __init__(self, context):
+        self.context = context
+        self._nova = {}
+        self._keystone = None
+        self._swift = None
+        self._quantum = None
+
+    def keystone(self):
+        if self._keystone:
+            return self._keystone
+
+        con = self.context
+        args = {
+            'auth_url': con.auth_url,
+        }
+
+        if con.password is not None:
+            args['username'] = con.username
+            args['password'] = con.password
+            args['tenant_name'] = con.tenant
+            args['tenant_id'] = con.tenant_id
+        elif con.auth_token is not None:
+            args['username'] = con.service_user
+            args['password'] = con.service_password
+            args['tenant_name'] = con.service_tenant
+            args['token'] = con.auth_token
+        else:
+            logger.error("Keystone connection failed, no password or " +
+                         "auth_token!")
+            return None
+
+        client = kc.Client(**args)
+        client.authenticate()
+        self._keystone = client
+        return self._keystone
+
+    def nova(self, service_type='compute'):
+        if service_type in self._nova:
+            return self._nova[service_type]
+
+        con = self.context
+        args = {
+            'project_id': con.tenant,
+            'auth_url': con.auth_url,
+            'service_type': service_type,
+        }
+
+        if con.password is not None:
+            args['username'] = con.username
+            args['api_key'] = con.password
+        elif con.auth_token is not None:
+            args['username'] = con.service_user
+            args['api_key'] = con.service_password
+            args['project_id'] = con.service_tenant
+            args['proxy_token'] = con.auth_token
+            args['proxy_tenant_id'] = con.tenant_id
+        else:
+            logger.error("Nova connection failed, no password or auth_token!")
+            return None
+
+        client = None
+        try:
+            # Workaround for issues with python-keyring, need no_cache=True
+            # ref https://bugs.launchpad.net/python-novaclient/+bug/1020238
+            # TODO(shardy): May be able to remove when the bug above is fixed
+            client = nc.Client(no_cache=True, **args)
+            client.authenticate()
+            self._nova[service_type] = client
+        except TypeError:
+            # for compatibility with essex, which doesn't have no_cache=True
+            # TODO(shardy): remove when we no longer support essex
+            client = nc.Client(**args)
+            client.authenticate()
+            self._nova[service_type] = client
+
+        return client
+
+    def swift(self):
+        if swiftclient_present == False:
+            return None
+        if self._swift:
+            return self._swift
+
+        con = self.context
+        args = {
+            'auth_version': '2'
+        }
+
+        if con.password is not None:
+            args['user'] = con.username
+            args['key'] = con.password
+            args['authurl'] = con.auth_url
+            args['tenant_name'] = con.tenant
+        elif con.auth_token is not None:
+            args['user'] = None
+            args['key'] = None
+            args['authurl'] = None
+            args['preauthtoken'] = con.auth_token
+            # Lookup endpoint for object-store service type
+            service_type = 'object-store'
+            endpoints = self.keystone().service_catalog.get_endpoints(
+                        service_type=service_type)
+            if len(endpoints[service_type]) == 1:
+                args['preauthurl'] = endpoints[service_type][0]['publicURL']
+            else:
+                logger.error("No endpoint found for %s service type" %
+                             service_type)
+                return None
+        else:
+            logger.error("Swift connection failed, no password or " +
+                         "auth_token!")
+            return None
+
+        self._swift = swiftclient.Connection(**args)
+        return self._swift
+
+    def quantum(self):
+        if quantumclient_present == False:
+            return None
+        if self._quantum:
+            logger.debug('using existing _quantum')
+            return self._quantum
+
+        con = self.context
+        args = {
+            'auth_url': con.auth_url,
+            '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['username'] = con.service_user
+            args['password'] = con.service_password
+            args['tenant_name'] = con.service_tenant
+            args['token'] = con.auth_token
+        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
index 2fc045d744bc5e0cf2c673e1a316fe766b3433b3..fc40a032a4e42f6458786975dcee049c1f2183ac 100644 (file)
@@ -26,6 +26,7 @@ from heat.engine import template
 from heat.engine import timestamp
 from heat.engine.parameters import Parameters
 from heat.engine.template import Template
+from heat.engine.clients import Clients
 from heat.db import api as db_api
 
 from heat.openstack.common import log as logging
@@ -61,6 +62,7 @@ class Stack(object):
         '''
         self.id = stack_id
         self.context = context
+        self.clients = Clients(context)
         self.t = tmpl
         self.name = stack_name
         self.state = state
index 186f5880121577ebe5153dbeb1745b37bf648fb7..a605a13376830c988ea2f00f5c6543851f6b52bd 100644 (file)
 import base64
 from datetime import datetime
 
-from novaclient.v1_1 import client as nc
-from keystoneclient.v2_0 import client as kc
-
-# swiftclient not available in all distributions - make s3 an optional
-# feature
-try:
-    from swiftclient import client as swiftclient
-    swiftclient_present = True
-except ImportError:
-    swiftclient_present = False
-# quantumclient not available in all distributions - make quantum an optional
-# feature
-try:
-    from quantumclient.v2_0 import client as quantumclient
-    quantumclient_present = True
-except ImportError:
-    quantumclient_present = False
-
 from heat.common import exception
 from heat.common import config
 from heat.db import api as db_api
@@ -184,145 +166,16 @@ class Resource(object):
         deps += (self, None)
 
     def keystone(self):
-        if self._keystone:
-            return self._keystone
-
-        con = self.context
-        args = {
-            'auth_url': con.auth_url,
-        }
-
-        if con.password is not None:
-            args['username'] = con.username
-            args['password'] = con.password
-            args['tenant_name'] = con.tenant
-            args['tenant_id'] = con.tenant_id
-        elif con.auth_token is not None:
-            args['username'] = con.service_user
-            args['password'] = con.service_password
-            args['tenant_name'] = con.service_tenant
-            args['token'] = con.auth_token
-        else:
-            logger.error("Keystone connection failed, no password or " +
-                         "auth_token!")
-            return None
-
-        client = kc.Client(**args)
-        client.authenticate()
-        self._keystone = client
-        return self._keystone
+        return self.stack.clients.keystone()
 
     def nova(self, service_type='compute'):
-        if service_type in self._nova:
-            return self._nova[service_type]
-
-        con = self.context
-        args = {
-            'project_id': con.tenant,
-            'auth_url': con.auth_url,
-            'service_type': service_type,
-        }
-
-        if con.password is not None:
-            args['username'] = con.username
-            args['api_key'] = con.password
-        elif con.auth_token is not None:
-            args['username'] = con.service_user
-            args['api_key'] = con.service_password
-            args['project_id'] = con.service_tenant
-            args['proxy_token'] = con.auth_token
-            args['proxy_tenant_id'] = con.tenant_id
-        else:
-            logger.error("Nova connection failed, no password or auth_token!")
-            return None
-
-        client = None
-        try:
-            # Workaround for issues with python-keyring, need no_cache=True
-            # ref https://bugs.launchpad.net/python-novaclient/+bug/1020238
-            # TODO(shardy): May be able to remove when the bug above is fixed
-            client = nc.Client(no_cache=True, **args)
-            client.authenticate()
-            self._nova[service_type] = client
-        except TypeError:
-            # for compatibility with essex, which doesn't have no_cache=True
-            # TODO(shardy): remove when we no longer support essex
-            client = nc.Client(**args)
-            client.authenticate()
-            self._nova[service_type] = client
-
-        return client
+        return self.stack.clients.nova(service_type)
 
     def swift(self):
-        if swiftclient_present == False:
-            return None
-        if self._swift:
-            return self._swift
-
-        con = self.context
-        args = {
-            'auth_version': '2'
-        }
-
-        if con.password is not None:
-            args['user'] = con.username
-            args['key'] = con.password
-            args['authurl'] = con.auth_url
-            args['tenant_name'] = con.tenant
-        elif con.auth_token is not None:
-            args['user'] = None
-            args['key'] = None
-            args['authurl'] = None
-            args['preauthtoken'] = con.auth_token
-            # Lookup endpoint for object-store service type
-            service_type = 'object-store'
-            endpoints = self.keystone().service_catalog.get_endpoints(
-                        service_type=service_type)
-            if len(endpoints[service_type]) == 1:
-                args['preauthurl'] = endpoints[service_type][0]['publicURL']
-            else:
-                logger.error("No endpoint found for %s service type" %
-                             service_type)
-                return None
-        else:
-            logger.error("Swift connection failed, no password or " +
-                         "auth_token!")
-            return None
-
-        self._swift = swiftclient.Connection(**args)
-        return self._swift
+        return self.stack.clients.swift()
 
     def quantum(self):
-        if quantumclient_present == False:
-            return None
-        if self._quantum:
-            logger.debug('using existing _quantum')
-            return self._quantum
-
-        con = self.context
-        args = {
-            'auth_url': con.auth_url,
-            '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['username'] = con.service_user
-            args['password'] = con.service_password
-            args['tenant_name'] = con.service_tenant
-            args['token'] = con.auth_token
-        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
+        return self.stack.clients.quantum()
 
     def create(self):
         '''