murano-deployment/heat-patches/0001-Adds-ability-to-config...

505 lines
16 KiB
Diff

From ac190f0da6ce367cc833b92677266e7bbf7e2270 Mon Sep 17 00:00:00 2001
From: Timur Sufiev <tsufiev@mirantis.com>
Date: Thu, 5 Dec 2013 19:46:28 +0400
Subject: [PATCH] Adds ability to configure various clients used by the Heat
This commit adds config sections [clients_nova], [clients_swift],
[clients_neutron], [clients_cinder], [clients_ceilometer] and
[clients_keystone]. These sections contain additional configuration
options for corresponding OpenStack clients.
Currently those are only SSL-related setting ca_file, cert_file,
key_file and insecure. Note, than not every client library is
currently capable of utilizing all of the SSL settings.
There is also a plain [clients] section that holds shared client
options. Each option searched first at specific group (clients_xxx)
and if it not found there then the value from [clients] group
are taken (or default values if there is no such setting in this
group). This allows defining shared configuration that would be
used by most (or all) clients without repeating the same settings
for each and every client separately
Closes-Bug: #1213122
Implements: blueprint clients-ssl-options
Ported from: icehouse.
---
etc/heat/heat.conf.sample | 182 ++++++++++++++++++++++++++++++++++---
heat/common/config.py | 28 +++++-
heat/common/heat_keystoneclient.py | 17 ++++
heat/engine/clients.py | 30 +++++-
heat/tests/test_heatclient.py | 36 ++++++--
5 files changed, 268 insertions(+), 25 deletions(-)
diff --git a/etc/heat/heat.conf.sample b/etc/heat/heat.conf.sample
index 1444f9b..20dadd3 100644
--- a/etc/heat/heat.conf.sample
+++ b/etc/heat/heat.conf.sample
@@ -473,6 +473,43 @@
#matchmaker_heartbeat_ttl=600
+[clients_swift]
+
+#
+# Options defined in heat.common.config
+#
+
+# Optional CA cert file to use in SSL connections (string
+# value)
+#ca_file=<None>
+
+# Optional PEM-formatted certificate chain file (string value)
+#cert_file=<None>
+
+# Optional PEM-formatted file that contains the private key
+# (string value)
+#key_file=<None>
+
+# If set then the server's certificate will not be verified
+# (boolean value)
+#insecure=false
+
+
+[auth_password]
+
+#
+# Options defined in heat.common.config
+#
+
+# Allow orchestration of multiple clouds (boolean value)
+#multi_cloud=false
+
+# Allowed keystone endpoints for auth_uri when multi_cloud is
+# enabled. At least one endpoint needs to be specified. (list
+# value)
+#allowed_auth_uris=
+
+
[ssl]
#
@@ -568,6 +605,104 @@
#api_paste_config=api-paste.ini
+[clients_cinder]
+
+#
+# Options defined in heat.common.config
+#
+
+# Optional CA cert file to use in SSL connections (string
+# value)
+#ca_file=<None>
+
+# Optional PEM-formatted certificate chain file (string value)
+#cert_file=<None>
+
+# Optional PEM-formatted file that contains the private key
+# (string value)
+#key_file=<None>
+
+# If set then the server's certificate will not be verified
+# (boolean value)
+#insecure=false
+
+
+[clients]
+
+#
+# Options defined in heat.common.config
+#
+
+# Optional CA cert file to use in SSL connections (string
+# value)
+#ca_file=<None>
+
+# Optional PEM-formatted certificate chain file (string value)
+#cert_file=<None>
+
+# Optional PEM-formatted file that contains the private key
+# (string value)
+#key_file=<None>
+
+# If set then the server's certificate will not be verified
+# (boolean value)
+#insecure=false
+
+
+[clients_nova]
+
+#
+# Options defined in heat.common.config
+#
+
+# Optional CA cert file to use in SSL connections (string
+# value)
+#ca_file=<None>
+
+# Optional PEM-formatted certificate chain file (string value)
+#cert_file=<None>
+
+# Optional PEM-formatted file that contains the private key
+# (string value)
+#key_file=<None>
+
+# If set then the server's certificate will not be verified
+# (boolean value)
+#insecure=false
+
+
+[matchmaker_ring]
+
+#
+# Options defined in heat.openstack.common.rpc.matchmaker_ring
+#
+
+# Matchmaker ring file (JSON) (string value)
+#ringfile=/etc/oslo/matchmaker_ring.json
+
+
+[clients_ceilometer]
+
+#
+# Options defined in heat.common.config
+#
+
+# Optional CA cert file to use in SSL connections (string
+# value)
+#ca_file=<None>
+
+# Optional PEM-formatted certificate chain file (string value)
+#cert_file=<None>
+
+# Optional PEM-formatted file that contains the private key
+# (string value)
+#key_file=<None>
+
+# If set then the server's certificate will not be verified
+# (boolean value)
+#insecure=false
+
+
[rpc_notifier2]
#
@@ -683,29 +818,26 @@
#workers=0
-[auth_password]
+[clients_neutron]
#
# Options defined in heat.common.config
#
-# Allow orchestration of multiple clouds (boolean value)
-#multi_cloud=false
-
-# Allowed keystone endpoints for auth_uri when multi_cloud is
-# enabled. At least one endpoint needs to be specified. (list
+# Optional CA cert file to use in SSL connections (string
# value)
-#allowed_auth_uris=
+#ca_file=<None>
+# Optional PEM-formatted certificate chain file (string value)
+#cert_file=<None>
-[matchmaker_ring]
+# Optional PEM-formatted file that contains the private key
+# (string value)
+#key_file=<None>
-#
-# Options defined in heat.openstack.common.rpc.matchmaker_ring
-#
-
-# Matchmaker ring file (JSON) (string value)
-#ringfile=/etc/oslo/matchmaker_ring.json
+# If set then the server's certificate will not be verified
+# (boolean value)
+#insecure=false
[matchmaker_redis]
@@ -724,3 +856,25 @@
#password=<None>
+[clients_keystone]
+
+#
+# Options defined in heat.common.config
+#
+
+# Optional CA cert file to use in SSL connections (string
+# value)
+#ca_file=<None>
+
+# Optional PEM-formatted certificate chain file (string value)
+#cert_file=<None>
+
+# Optional PEM-formatted file that contains the private key
+# (string value)
+#key_file=<None>
+
+# If set then the server's certificate will not be verified
+# (boolean value)
+#insecure=false
+
+
diff --git a/heat/common/config.py b/heat/common/config.py
index 82b4ca5..b115f20 100644
--- a/heat/common/config.py
+++ b/heat/common/config.py
@@ -17,7 +17,7 @@
"""
Routines for configuring Heat
"""
-
+import copy
import logging as sys_logging
import os
@@ -133,6 +133,31 @@ auth_password_opts = [
help=_('Allowed keystone endpoints for auth_uri when '
'multi_cloud is enabled. At least one endpoint needs '
'to be specified.'))]
+clients_opts = [
+ cfg.StrOpt('ca_file',
+ help=_('Optional CA cert file to use in SSL connections')),
+ cfg.StrOpt('cert_file',
+ help=_('Optional PEM-formatted certificate chain file')),
+ cfg.StrOpt('key_file',
+ help=_('Optional PEM-formatted file that contains the '
+ 'private key')),
+ cfg.BoolOpt('insecure',
+ default=False,
+ help=_("If set then the server's certificate will not "
+ "be verified"))]
+
+
+def register_clients_opts():
+ cfg.CONF.register_opts(clients_opts, group='clients')
+ for client in ('nova', 'swift', 'neutron', 'cinder',
+ 'ceilometer', 'keystone'):
+ client_specific_group = 'clients_' + client
+ # register opts copy and put it to globals in order to
+ # generate_sample.sh to work
+ opts_copy = copy.deepcopy(clients_opts)
+ globals()[client_specific_group + '_opts'] = opts_copy
+ cfg.CONF.register_opts(opts_copy, group=client_specific_group)
+
cfg.CONF.register_opts(db_opts)
cfg.CONF.register_opts(engine_opts)
@@ -142,6 +167,7 @@ cfg.CONF.register_group(paste_deploy_group)
cfg.CONF.register_opts(paste_deploy_opts, group=paste_deploy_group)
cfg.CONF.register_group(auth_password_group)
cfg.CONF.register_opts(auth_password_opts, group=auth_password_group)
+register_clients_opts()
def rpc_set_default():
diff --git a/heat/common/heat_keystoneclient.py b/heat/common/heat_keystoneclient.py
index 8fb13f7..d052a67 100644
--- a/heat/common/heat_keystoneclient.py
+++ b/heat/common/heat_keystoneclient.py
@@ -100,6 +100,10 @@ class KeystoneClient(object):
logger.error("Keystone v2 API connection failed, no password or "
"auth_token!")
raise exception.AuthorizationFailure()
+ kwargs['cacert'] = self._get_client_option('ca_file')
+ kwargs['insecure'] = self._get_client_option('insecure')
+ kwargs['cert'] = self._get_client_option('cert_file')
+ kwargs['key'] = self._get_client_option('key_file')
client_v2 = kc.Client(**kwargs)
client_v2.authenticate(**auth_kwargs)
@@ -161,12 +165,25 @@ class KeystoneClient(object):
"auth_token!")
raise exception.AuthorizationFailure()
+ kwargs['cacert'] = self._get_client_option('ca_file')
+ kwargs['insecure'] = self._get_client_option('insecure')
+ kwargs['cert'] = self._get_client_option('cert_file')
+ kwargs['key'] = self._get_client_option('key_file')
client = kc_v3.Client(**kwargs)
# Have to explicitly authenticate() or client.auth_ref is None
client.authenticate()
return client
+ def _get_client_option(self, option):
+ try:
+ cfg.CONF.import_opt(option, 'heat.common.config',
+ group='clients_keystone')
+ return getattr(cfg.CONF.clients_keystone, option)
+ except (cfg.NoSuchGroupError, cfg.NoSuchOptError):
+ cfg.CONF.import_opt(option, 'heat.common.config', group='clients')
+ return getattr(cfg.CONF.clients, option)
+
def create_trust_context(self):
"""
If cfg.CONF.deferred_auth_method is trusts, we create a
diff --git a/heat/engine/clients.py b/heat/engine/clients.py
index 6deae5b..a749cd2 100644
--- a/heat/engine/clients.py
+++ b/heat/engine/clients.py
@@ -103,7 +103,9 @@ class OpenStackClients(object):
'service_type': service_type,
'username': None,
'api_key': None,
- 'extensions': extensions
+ 'extensions': extensions,
+ 'cacert': self._get_client_option('nova', 'ca_file'),
+ 'insecure': self._get_client_option('nova', 'insecure')
}
client = novaclient.Client(1.1, **args)
@@ -133,7 +135,9 @@ class OpenStackClients(object):
'key': None,
'authurl': None,
'preauthtoken': self.auth_token,
- 'preauthurl': self.url_for(service_type='object-store')
+ 'preauthurl': self.url_for(service_type='object-store'),
+ 'cacert': self._get_client_option('swift', 'ca_file'),
+ 'insecure': self._get_client_option('swift', 'insecure')
}
self._swift = swiftclient.Connection(**args)
return self._swift
@@ -153,7 +157,9 @@ class OpenStackClients(object):
'auth_url': con.auth_url,
'service_type': 'network',
'token': self.auth_token,
- 'endpoint_url': self.url_for(service_type='network')
+ 'endpoint_url': self.url_for(service_type='network'),
+ 'ca_cert': self._get_client_option('neutron', 'ca_file'),
+ 'insecure': self._get_client_option('neutron', 'insecure')
}
self._neutron = neutronclient.Client(**args)
@@ -176,7 +182,9 @@ class OpenStackClients(object):
'auth_url': con.auth_url,
'project_id': con.tenant,
'username': None,
- 'api_key': None
+ 'api_key': None,
+ 'cacert': self._get_client_option('cinder', 'ca_file'),
+ 'insecure': self._get_client_option('cinder', 'insecure')
}
self._cinder = cinderclient.Client('1', **args)
@@ -202,6 +210,10 @@ class OpenStackClients(object):
'project_id': con.tenant,
'token': lambda: self.auth_token,
'endpoint': self.url_for(service_type='metering'),
+ '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(**args)
@@ -209,6 +221,16 @@ class OpenStackClients(object):
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)
+
if cfg.CONF.cloud_backend:
cloud_backend_module = importutils.import_module(cfg.CONF.cloud_backend)
diff --git a/heat/tests/test_heatclient.py b/heat/tests/test_heatclient.py
index 7e195dc..712ffa5 100644
--- a/heat/tests/test_heatclient.py
+++ b/heat/tests/test_heatclient.py
@@ -51,7 +51,11 @@ class KeystoneClientTest(HeatTestCase):
self.mock_ks_client = heat_keystoneclient.kc.Client(
auth_url=mox.IgnoreArg(),
tenant_name='test_tenant',
- token='abcd1234')
+ token='abcd1234',
+ cacert=None,
+ cert=None,
+ insecure=False,
+ key=None)
self.mock_ks_client.authenticate().AndReturn(auth_ok)
elif method == 'password':
self.mock_ks_client = heat_keystoneclient.kc.Client(
@@ -59,14 +63,22 @@ class KeystoneClientTest(HeatTestCase):
tenant_name='test_tenant',
tenant_id='test_tenant_id',
username='test_username',
- password='password')
+ password='password',
+ cacert=None,
+ cert=None,
+ insecure=False,
+ key=None)
self.mock_ks_client.authenticate().AndReturn(auth_ok)
if method == 'trust':
self.mock_ks_client = heat_keystoneclient.kc.Client(
auth_url='http://server.test:5000/v2.0',
password='verybadpass',
tenant_name='service',
- username='heat')
+ username='heat',
+ cacert=None,
+ cert=None,
+ insecure=False,
+ key=None)
self.mock_ks_client.authenticate(trust_id='atrust123',
tenant_id='test_tenant_id'
).AndReturn(auth_ok)
@@ -81,7 +93,11 @@ class KeystoneClientTest(HeatTestCase):
self.mock_ks_v3_client = heat_keystoneclient.kc_v3.Client(
token='abcd1234', project_name='test_tenant',
auth_url='http://server.test:5000/v3',
- endpoint='http://server.test:5000/v3')
+ endpoint='http://server.test:5000/v3',
+ cacert=None,
+ cert=None,
+ insecure=False,
+ key=None)
elif method == 'password':
self.mock_ks_v3_client = heat_keystoneclient.kc_v3.Client(
username='test_username',
@@ -89,13 +105,21 @@ class KeystoneClientTest(HeatTestCase):
project_name='test_tenant',
project_id='test_tenant_id',
auth_url='http://server.test:5000/v3',
- endpoint='http://server.test:5000/v3')
+ endpoint='http://server.test:5000/v3',
+ cacert=None,
+ cert=None,
+ insecure=False,
+ key=None)
elif method == 'trust':
self.mock_ks_v3_client = heat_keystoneclient.kc_v3.Client(
username='heat',
password='verybadpass',
project_name='service',
- auth_url='http://server.test:5000/v3')
+ auth_url='http://server.test:5000/v3',
+ cacert=None,
+ cert=None,
+ insecure=False,
+ key=None)
self.mock_ks_v3_client.authenticate().AndReturn(auth_ok)
def test_username_length(self):
--
1.8.3.2