heat/heat/engine/clients.py

309 lines
11 KiB
Python

#
# 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 ceilometerclient import client as ceilometerclient
from cinderclient import client as cinderclient
from glanceclient import client as glanceclient
from heatclient import client as heatclient
from neutronclient.v2_0 import client as neutronclient
from novaclient import client as novaclient
from novaclient import shell as novashell
from oslo.config import cfg
from swiftclient import client as swiftclient
from troveclient import client as troveclient
from heat.common import heat_keystoneclient as hkc
from heat.openstack.common.gettextutils import _
from heat.openstack.common import importutils
from heat.openstack.common import log as logging
LOG = logging.getLogger(__name__)
_default_backend = "heat.engine.clients.OpenStackClients"
cloud_opts = [
cfg.StrOpt('cloud_backend',
default=_default_backend,
help="Fully qualified class name to use as a client backend.")
]
cfg.CONF.register_opts(cloud_opts)
class OpenStackClients(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._neutron = None
self._cinder = None
self._trove = None
self._ceilometer = None
self._heat = None
self._glance = 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
self._keystone = hkc.KeystoneClient(self.context)
return self._keystone
def url_for(self, **kwargs):
return self.keystone().url_for(**kwargs)
def nova(self, service_type='compute'):
if service_type in self._nova:
return self._nova[service_type]
con = self.context
computeshell = novashell.OpenStackComputeShell()
extensions = computeshell._discover_extensions("1.1")
endpoint_type = self._get_client_option('nova', 'endpoint_type')
args = {
'project_id': con.tenant,
'auth_url': con.auth_url,
'service_type': service_type,
'username': None,
'api_key': None,
'extensions': extensions,
'endpoint_type': endpoint_type,
'cacert': self._get_client_option('nova', 'ca_file'),
'insecure': self._get_client_option('nova', 'insecure')
}
client = novaclient.Client(1.1, **args)
management_url = self.url_for(service_type=service_type,
endpoint_type=endpoint_type)
client.client.auth_token = self.auth_token
client.client.management_url = management_url
self._nova[service_type] = client
return client
def swift(self):
if self._swift:
return self._swift
con = self.context
endpoint_type = self._get_client_option('swift', 'endpoint_type')
args = {
'auth_version': '2.0',
'tenant_name': con.tenant,
'user': con.username,
'key': None,
'authurl': None,
'preauthtoken': self.auth_token,
'preauthurl': self.url_for(service_type='object-store',
endpoint_type=endpoint_type),
'os_options': {'endpoint_type': endpoint_type},
'cacert': self._get_client_option('swift', 'ca_file'),
'insecure': self._get_client_option('swift', 'insecure')
}
self._swift = swiftclient.Connection(**args)
return self._swift
def glance(self):
if self._glance:
return self._glance
con = self.context
endpoint_type = self._get_client_option('glance', 'endpoint_type')
endpoint = self.url_for(service_type='image',
endpoint_type=endpoint_type)
args = {
'auth_url': con.auth_url,
'service_type': 'image',
'project_id': con.tenant,
'token': self.auth_token,
'endpoint_type': endpoint_type,
'ca_file': self._get_client_option('glance', 'ca_file'),
'cert_file': self._get_client_option('glance', 'cert_file'),
'key_file': self._get_client_option('glance', 'key_file'),
'insecure': self._get_client_option('glance', 'insecure')
}
self._glance = glanceclient.Client('1', endpoint, **args)
return self._glance
def neutron(self):
if self._neutron:
return self._neutron
con = self.context
if self.auth_token is None:
LOG.error(_("Neutron connection failed, no auth_token!"))
return None
endpoint_type = self._get_client_option('neutron', 'endpoint_type')
args = {
'auth_url': con.auth_url,
'service_type': 'network',
'token': self.auth_token,
'endpoint_url': self.url_for(service_type='network',
endpoint_type=endpoint_type),
'endpoint_type': endpoint_type,
'ca_cert': self._get_client_option('neutron', 'ca_file'),
'insecure': self._get_client_option('neutron', 'insecure')
}
self._neutron = neutronclient.Client(**args)
return self._neutron
def cinder(self):
if self._cinder:
return self._cinder
con = self.context
endpoint_type = self._get_client_option('cinder', 'endpoint_type')
args = {
'service_type': 'volume',
'auth_url': con.auth_url,
'project_id': con.tenant,
'username': None,
'api_key': None,
'endpoint_type': endpoint_type,
'cacert': self._get_client_option('cinder', 'ca_file'),
'insecure': self._get_client_option('cinder', 'insecure')
}
self._cinder = cinderclient.Client('1', **args)
management_url = self.url_for(service_type='volume',
endpoint_type=endpoint_type)
self._cinder.client.auth_token = self.auth_token
self._cinder.client.management_url = management_url
return self._cinder
def trove(self, service_type="database"):
if self._trove:
return self._trove
con = self.context
endpoint_type = self._get_client_option('trove', 'endpoint_type')
args = {
'service_type': service_type,
'auth_url': con.auth_url,
'proxy_token': con.auth_token,
'username': None,
'password': None,
'cacert': self._get_client_option('trove', 'ca_file'),
'insecure': self._get_client_option('trove', 'insecure'),
'endpoint_type': endpoint_type
}
self._trove = troveclient.Client('1.0', **args)
management_url = self.url_for(service_type=service_type,
endpoint_type=endpoint_type)
self._trove.client.auth_token = con.auth_token
self._trove.client.management_url = management_url
return self._trove
def ceilometer(self):
if self._ceilometer:
return self._ceilometer
con = self.context
endpoint_type = self._get_client_option('ceilometer', 'endpoint_type')
endpoint = self.url_for(service_type='metering',
endpoint_type=endpoint_type)
args = {
'auth_url': con.auth_url,
'service_type': 'metering',
'project_id': con.tenant,
'token': lambda: self.auth_token,
'endpoint_type': endpoint_type,
'ca_file': self._get_client_option('ceilometer', 'ca_file'),
'cert_file': self._get_client_option('ceilometer', 'cert_file'),
'key_file': self._get_client_option('ceilometer', 'key_file'),
'insecure': self._get_client_option('ceilometer', 'insecure')
}
client = ceilometerclient.Client('2', endpoint, **args)
self._ceilometer = client
return self._ceilometer
def _get_client_option(self, client, option):
try:
group_name = 'clients_' + client
cfg.CONF.import_opt(option, 'heat.common.config',
group=group_name)
return getattr(getattr(cfg.CONF, group_name), option)
except (cfg.NoSuchGroupError, cfg.NoSuchOptError):
cfg.CONF.import_opt(option, 'heat.common.config', group='clients')
return getattr(cfg.CONF.clients, option)
def _get_heat_url(self):
heat_url = self._get_client_option('heat', 'url')
if heat_url:
tenant_id = self.context.tenant_id
heat_url = heat_url % {'tenant_id': tenant_id}
return heat_url
def heat(self):
if self._heat:
return self._heat
con = self.context
endpoint_type = self._get_client_option('heat', 'endpoint_type')
args = {
'auth_url': con.auth_url,
'token': self.auth_token,
'username': None,
'password': None,
'ca_file': self._get_client_option('heat', 'ca_file'),
'cert_file': self._get_client_option('heat', 'cert_file'),
'key_file': self._get_client_option('heat', 'key_file'),
'insecure': self._get_client_option('heat', 'insecure')
}
endpoint = self._get_heat_url()
if not endpoint:
endpoint = self.url_for(service_type='orchestration',
endpoint_type=endpoint_type)
self._heat = heatclient.Client('1', endpoint, **args)
return self._heat
class ClientBackend(object):
'''Delay choosing the backend client module until the client's class needs
to be initialized.
'''
def __new__(cls, context):
if cfg.CONF.cloud_backend == _default_backend:
return OpenStackClients(context)
else:
return importutils.import_object(
cfg.CONF.cloud_backend,
context
)
Clients = ClientBackend