Determine default port based on presence of TLS configuration

Fix intermittent deployment failure with TLS.

Default to TLS in the functional test.

The call to ``configure_https`` in identity_changed is remains
from the time when Keystone provided certificates, remove it.

Hold service down until keys are rendered.

Change-Id: Ia16e6200520972c503102d80cda35e36daea82a2
Closes-Bug: #1868387
(cherry picked from commit d544c70912)
This commit is contained in:
Frode Nordahl 2020-03-23 08:26:19 +01:00 committed by Dmitrii Shcherbakov
parent b2a0fdecf2
commit ec5ece070e
21 changed files with 246 additions and 47 deletions

View File

@ -55,9 +55,12 @@ options:
natively supported config in the charm.
port:
type: int
default: 80
default:
description: |
The port that the RADOS Gateway will listen on.
.
The default is 80 when no TLS is configured and 443 when TLS is
configured.
prefer-ipv6:
type: boolean
default: False

View File

@ -41,13 +41,15 @@ from charmhelpers.contrib.network.ip import (
)
from charmhelpers.contrib.storage.linux.ceph import CephConfContext
import utils
class ApacheSSLContext(context.ApacheSSLContext):
interfaces = ['https']
service_namespace = 'ceph-radosgw'
def __call__(self):
self.external_ports = [config('port')]
self.external_ports = [utils.listen_port()]
return super(ApacheSSLContext, self).__call__()
@ -55,7 +57,7 @@ class HAProxyContext(context.HAProxyContext):
def __call__(self):
ctxt = super(HAProxyContext, self).__call__()
port = config('port')
port = utils.listen_port()
# Apache ports
a_cephradosgw_api = determine_apache_port(port, singlenode_mode=True)
@ -183,7 +185,7 @@ class MonContext(context.CephContext):
if config('prefer-ipv6'):
ensure_host_resolvable_v6(host)
port = determine_api_port(config('port'), singlenode_mode=True)
port = determine_api_port(utils.listen_port(), singlenode_mode=True)
if config('prefer-ipv6'):
port = "[::]:%s" % (port)

View File

@ -53,10 +53,12 @@ from charmhelpers.payload.execd import execd_preinstall
from charmhelpers.core.host import (
cmp_pkgrevno,
is_container,
service,
service_pause,
service_reload,
service_restart,
service_resume,
service_stop,
service,
)
from charmhelpers.contrib.network.ip import (
get_relation_ip,
@ -80,20 +82,21 @@ from charmhelpers.contrib.openstack.ha.utils import (
generate_ha_relation_data,
)
from utils import (
register_configs,
setup_ipv6,
services,
assess_status,
disable_unused_apache_sites,
pause_unit_helper,
resume_unit_helper,
restart_map,
service_name,
systemd_based_radosgw,
request_per_unit_key,
ready_for_service,
restart_nonce_changed,
listen_port,
multisite_deployment,
pause_unit_helper,
ready_for_service,
register_configs,
request_per_unit_key,
restart_map,
restart_nonce_changed,
resume_unit_helper,
service_name,
services,
setup_ipv6,
systemd_based_radosgw,
)
from charmhelpers.contrib.charmsupport import nrpe
from charmhelpers.contrib.hardening.harden import harden
@ -168,6 +171,10 @@ def install():
status_set('maintenance', 'Executing pre-install')
execd_preinstall()
install_packages()
# hold the service down until we have keys from ceph
log('Disable service "{}" until we have keys for it.'
.format(service_name()), level=DEBUG)
service_pause(service_name())
if not os.path.exists('/etc/ceph'):
os.makedirs('/etc/ceph')
if is_leader():
@ -225,7 +232,7 @@ def config_changed():
update_nrpe_config()
open_port(port=config('port'))
open_port(port=listen_port())
_config_changed()
@ -270,7 +277,6 @@ def mon_relation(rid=None, unit=None):
# host services.
update_nrpe_config(checks_to_remove=['radosgw'])
service('enable', service_name())
# NOTE(jamespage):
# Multi-site deployments need to defer restart as the
# zone is not created until the master relation is
@ -280,7 +286,9 @@ def mon_relation(rid=None, unit=None):
if (not is_unit_paused_set() and
new_keyring and
not multisite_deployment()):
service_restart(service_name())
log('Resume service "{}" as we now have keys for it.'
.format(service_name()), level=DEBUG)
service_resume(service_name())
process_multisite_relations()
else:
@ -291,7 +299,7 @@ def mon_relation(rid=None, unit=None):
@hooks.hook('gateway-relation-joined')
def gateway_relation():
relation_set(hostname=get_relation_ip('gateway-relation'),
port=config('port'))
port=listen_port())
@hooks.hook('identity-service-relation-joined')
@ -300,7 +308,7 @@ def identity_joined(relid=None):
log('Integration with keystone requires ceph >= 0.55')
sys.exit(1)
port = config('port')
port = listen_port()
admin_url = '%s:%i/swift' % (canonical_url(CONFIGS, ADMIN), port)
if leader_get('namespace_tenants') == 'True':
internal_url = '%s:%s/swift/v1/AUTH_$(project_id)s' % \
@ -341,7 +349,6 @@ def identity_changed(relid=None):
def _identity_changed():
identity_joined(relid)
CONFIGS.write_all()
configure_https()
_identity_changed()
@ -492,7 +499,7 @@ def master_relation_joined(relation_id=None):
internal_url = '{}:{}'.format(
canonical_url(CONFIGS, INTERNAL),
config('port')
listen_port(),
)
endpoints = [internal_url]
realm = config('realm')
@ -582,7 +589,7 @@ def slave_relation_changed(relation_id=None, unit=None):
internal_url = '{}:{}'.format(
canonical_url(CONFIGS, INTERNAL),
config('port')
listen_port(),
)
endpoints = [internal_url]

View File

@ -100,6 +100,22 @@ BASE_RESOURCE_MAP = OrderedDict([
])
def listen_port():
"""Determine port to listen to.
The value in configuration will be used if specified, otherwise the default
will be determined based on presence of TLS configuration.
:returns: Port number
:rtype: int
"""
if https():
default_port = 443
else:
default_port = 80
return config('port') or default_port
def resource_map():
"""Dynamically generate a map of resources.

View File

@ -33,6 +33,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -42,3 +45,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -32,6 +32,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -41,3 +44,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -33,6 +33,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -42,3 +45,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -32,6 +32,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -41,3 +44,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -33,6 +33,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -42,3 +45,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -32,6 +32,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -41,3 +44,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -32,6 +32,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -41,3 +44,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -31,6 +31,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -40,3 +43,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -32,6 +32,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -41,3 +44,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -31,6 +31,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -40,3 +43,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -20,6 +20,7 @@ machines:
'8':
'9':
'10':
'11':
applications:
@ -78,6 +79,15 @@ applications:
to:
- '10'
vault-mysql-router:
charm: cs:~openstack-charmers-next/mysql-router
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
to:
- '11'
relations:
- - 'keystone:shared-db'
@ -94,3 +104,14 @@ relations:
- - 'ceph-radosgw:identity-service'
- 'keystone:identity-service'
- - 'vault-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'vault:shared-db'
- 'vault-mysql-router:shared-db'
- - 'keystone:certificates'
- 'vault:certificates'
- - 'ceph-radosgw:certificates'
- 'vault:certificates'

View File

@ -20,6 +20,7 @@ machines:
'8':
'9':
'10':
'11':
applications:
@ -77,6 +78,15 @@ applications:
to:
- '10'
vault-mysql-router:
charm: cs:~openstack-charmers-next/mysql-router
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
to:
- '11'
relations:
- - 'keystone:shared-db'
@ -92,3 +102,15 @@ relations:
- - 'ceph-radosgw:identity-service'
- 'keystone:identity-service'
- - 'vault-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'vault:shared-db'
- 'vault-mysql-router:shared-db'
- - 'keystone:certificates'
- 'vault:certificates'
- - 'ceph-radosgw:certificates'
- 'vault:certificates'

View File

@ -32,6 +32,9 @@ applications:
num_units: 1
options:
openstack-origin: *source
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
relations:
- - keystone:shared-db
- percona-cluster:shared-db
@ -41,3 +44,9 @@ relations:
- ceph-mon:radosgw
- - ceph-radosgw:identity-service
- keystone:identity-service
- - vault:shared-db
- percona-cluster:shared-db
- - keystone:certificates
- vault:certificates
- - ceph-radosgw:certificates
- vault:certificates

View File

@ -1,31 +1,39 @@
charm_name: ceph-radosgw
gate_bundles:
- test-s3api: focal-ussuri
- test-s3api: focal-ussuri-namespaced
- test-s3api: bionic-ussuri
- test-s3api: bionic-ussuri-namespaced
- test-s3api: bionic-train
- test-s3api: bionic-train-namespaced
- test-s3api: bionic-stein
- test-s3api: bionic-stein-namespaced
- test-s3api: bionic-rocky
- test-s3api: bionic-rocky-namespaced
- test-s3api: bionic-queens
- test-s3api: bionic-queens-namespaced
- test-s3api: xenial-queens
- vault: focal-ussuri
- vault: focal-ussuri-namespaced
- vault: bionic-ussuri
- vault: bionic-ussuri-namespaced
- vault: bionic-train
- vault: bionic-train-namespaced
- vault: bionic-stein
- vault: bionic-stein-namespaced
- vault: bionic-rocky
- vault: bionic-rocky-namespaced
- vault: bionic-queens
- vault: bionic-queens-namespaced
- vault: xenial-queens
- xenial-pike
- xenial-ocata
- xenial-mitaka
- xenial-mitaka-namespaced
- trusty-mitaka
smoke_bundles:
- test-s3api: bionic-train
- vault: bionic-ussuri
dev_bundles:
- vault: focal-ussuri
- bionic-queens-multisite
- bionic-rocky-multisite
target_deploy_status:
vault:
workload-status: blocked
workload-status-message: Vault needs to be initialized
configure:
- vault:
- zaza.openstack.charm_tests.vault.setup.auto_initialize
tests:
- zaza.openstack.charm_tests.ceph.tests.CephRGWTest
- test-s3api:
- vault:
- zaza.openstack.charm_tests.ceph.tests.CephRGWTest
- zaza.openstack.charm_tests.swift.tests.S3APITest
tests_options:

View File

@ -32,6 +32,7 @@ TO_PATCH = [
'determine_api_port',
'cmp_pkgrevno',
'leader_get',
'utils',
]
@ -59,6 +60,7 @@ class HAProxyContextTests(CharmTestCase):
_haconfig.side_effect = self.test_config.get
_harelation_ids.return_value = []
haproxy_context = context.HAProxyContext()
self.utils.listen_port.return_value = 80
self.determine_api_port.return_value = 70
expect = {
'cephradosgw_bind_port': 70,

View File

@ -300,3 +300,11 @@ class CephRadosGWUtilTests(CharmTestCase):
self.assertTrue(utils.multisite_deployment())
self.test_config.set('realm', None)
self.assertFalse(utils.multisite_deployment())
def test_listen_port(self):
self.https.return_value = False
self.assertEquals(80, utils.listen_port())
self.https.return_value = True
self.assertEquals(443, utils.listen_port())
self.test_config.set('port', 42)
self.assertEquals(42, utils.listen_port())

View File

@ -37,6 +37,7 @@ TO_PATCH = [
'config',
'cmp_pkgrevno',
'execd_preinstall',
'listen_port',
'log',
'open_port',
'os',
@ -53,6 +54,8 @@ TO_PATCH = [
'service_reload',
'service_stop',
'service_restart',
'service_pause',
'service_resume',
'service',
'service_name',
'socket',
@ -155,6 +158,7 @@ class CephRadosGWTests(CharmTestCase):
self.assertTrue(_install_packages.called)
is_leader.assert_called_once()
leader_set.assert_called_once_with(namespace_tenants=False)
self.service_pause.assert_called_once_with('radosgw')
@patch.object(ceph_hooks, 'leader_set')
@patch.object(ceph_hooks, 'is_leader')
@ -167,6 +171,7 @@ class CephRadosGWTests(CharmTestCase):
self.assertTrue(_install_packages.called)
is_leader.assert_called_once()
leader_set.assert_called_once_with(namespace_tenants=True)
self.service_pause.assert_called_once_with('radosgw')
@patch.object(ceph_hooks, 'certs_joined')
@patch.object(ceph_hooks, 'update_nrpe_config')
@ -191,8 +196,7 @@ class CephRadosGWTests(CharmTestCase):
self.socket.gethostname.return_value = 'testinghostname'
ceph_hooks.mon_relation()
self.relation_set.assert_not_called()
self.service_restart.assert_called_once_with('radosgw')
self.service.assert_called_once_with('enable', 'radosgw')
self.service_resume.assert_called_once_with('radosgw')
_ceph.import_radosgw_key.assert_called_with('seckey',
name='rgw.testinghostname')
self.CONFIGS.write_all.assert_called_with()
@ -210,8 +214,7 @@ class CephRadosGWTests(CharmTestCase):
relation_id=None,
key_name='rgw.testinghostname'
)
self.service_restart.assert_called_once_with('radosgw')
self.service.assert_called_once_with('enable', 'radosgw')
self.service_resume.assert_called_once_with('radosgw')
_ceph.import_radosgw_key.assert_called_with('seckey',
name='rgw.testinghostname')
self.CONFIGS.write_all.assert_called_with()
@ -224,8 +227,7 @@ class CephRadosGWTests(CharmTestCase):
self.relation_get.return_value = None
ceph_hooks.mon_relation()
self.assertFalse(_ceph.import_radosgw_key.called)
self.service_restart.assert_not_called()
self.service.assert_not_called()
self.service_resume.assert_not_called()
self.CONFIGS.write_all.assert_called_with()
@patch.object(ceph_hooks, 'send_request_if_needed')
@ -237,14 +239,14 @@ class CephRadosGWTests(CharmTestCase):
_ceph.import_radosgw_key.return_value = False
self.relation_get.return_value = 'seckey'
ceph_hooks.mon_relation()
self.service_restart.assert_not_called()
self.service.assert_not_called()
self.service_resume.assert_not_called()
self.assertFalse(_ceph.import_radosgw_key.called)
self.assertFalse(self.CONFIGS.called)
self.assertTrue(mock_send_request_if_needed.called)
def test_gateway_relation(self):
self.get_relation_ip.return_value = '10.0.0.1'
self.listen_port.return_value = 80
ceph_hooks.gateway_relation()
self.relation_set.assert_called_with(hostname='10.0.0.1', port=80)
@ -255,6 +257,7 @@ class CephRadosGWTests(CharmTestCase):
def test_identity_joined_early_version(self, _config, _leader_get):
self.cmp_pkgrevno.return_value = -1
_leader_get.return_value = 'False'
self.listen_port.return_value = 80
ceph_hooks.identity_joined()
self.sys.exit.assert_called_with(1)
@ -265,6 +268,8 @@ class CephRadosGWTests(CharmTestCase):
@patch('charmhelpers.contrib.openstack.ip.config')
def test_identity_joined(self, _config, _resolve_address, _leader_get):
self.listen_port.return_value = 80
def _test_identify_joined(expected):
self.related_units = ['unit/0']
self.cmp_pkgrevno.return_value = 1
@ -310,6 +315,7 @@ class CephRadosGWTests(CharmTestCase):
def _test_identify_joined(expected):
self.related_units = ['unit/0']
self.cmp_pkgrevno.return_value = 1
self.listen_port.return_value = 80
_resolve_address.return_value = 'myserv'
_config.side_effect = self.test_config.get
self.test_config.set('region', 'region1')
@ -356,6 +362,7 @@ class CephRadosGWTests(CharmTestCase):
_unit_get.return_value = 'myserv'
_is_clustered.return_value = False
_leader_get.return_value = 'False'
self.listen_port.return_value = 80
ceph_hooks.identity_joined(relid='rid')
self.relation_set.assert_has_calls([
call(swift_service='swift',
@ -521,6 +528,7 @@ class CephRadosMultisiteTests(CharmTestCase):
'relation_set',
'relation_get',
'leader_get',
'listen_port',
'config',
'is_leader',
'multisite',
@ -574,6 +582,7 @@ class MasterMultisiteTests(CephRadosMultisiteTests):
def test_master_relation_joined_create_everything(self):
for k, v in self._complete_config.items():
self.test_config.set(k, v)
self.listen_port.return_value = 80
self.is_leader.return_value = True
self.leader_get.side_effect = lambda attr: self._leader_data.get(attr)
self.multisite.list_realms.return_value = []
@ -656,6 +665,7 @@ class MasterMultisiteTests(CephRadosMultisiteTests):
def test_master_relation_joined_not_leader(self):
for k, v in self._complete_config.items():
self.test_config.set(k, v)
self.listen_port.return_value = 80
self.is_leader.return_value = False
self.leader_get.side_effect = lambda attr: self._leader_data.get(attr)
ceph_hooks.master_relation_joined('master:1')
@ -698,6 +708,7 @@ class SlaveMultisiteTests(CephRadosMultisiteTests):
for k, v in self._complete_config.items():
self.test_config.set(k, v)
self.is_leader.return_value = True
self.listen_port.return_value = 80
self.leader_get.return_value = None
self.relation_get.return_value = self._test_relation
self.multisite.list_realms.return_value = []