Merge "Remove endpoint_type from configuration"

This commit is contained in:
Zuul 2018-07-23 22:08:33 +00:00 committed by Gerrit Code Review
commit fcc2088409
14 changed files with 92 additions and 251 deletions

View File

@ -8,7 +8,7 @@ Overview
======== ========
Ceph project is a powerful distributed storage system. It contains object store Ceph project is a powerful distributed storage system. It contains object store
and provides a RADOS Gateway Swift API which is compatible with OpenStack Swift and provides a RADOS Gateway Swift API which is compatible with OpenStack Swift
API. These two APIs use different formats for their temporary URLs. API.
Ironic added support for RADOS Gateway temporary URL in the Mitaka release. Ironic added support for RADOS Gateway temporary URL in the Mitaka release.
@ -17,56 +17,56 @@ Configure Ironic and Glance with RADOS Gateway
#. Install Ceph storage with RADOS Gateway. See `Ceph documentation <http://docs.ceph.com/docs>`_. #. Install Ceph storage with RADOS Gateway. See `Ceph documentation <http://docs.ceph.com/docs>`_.
#. Create RADOS Gateway credentials for Glance by executing the following #. Configure RADOS Gateway to use keystone for authentication. See
commands on the RADOS Gateway admin host:: `Integrating with OpenStack Keystone <http://docs.ceph.com/docs/master/radosgw/keystone/>`_
sudo radosgw-admin user create --uid="GLANCE_USERNAME" --display-name="User for Glance" #. Register RADOS Gateway endpoint in the keystone catalog, with the same
format swift uses, as the ``object-store`` service. URL example:
sudo radosgw-admin subuser create --uid=GLANCE_USERNAME --subuser=GLANCE_USERNAME:swift --access=full ``http://rados.example.com:8080/swift/v1/AUTH_$(project_id)s``.
sudo radosgw-admin key create --subuser=GLANCE_USERNAME:swift --key-type=swift --secret=STORE_KEY In the ceph configuration, make sure radosgw is configured with the
following value::
sudo radosgw-admin user modify --uid=GLANCE_USERNAME --temp-url-key=TEMP_URL_KEY rgw swift account in url = True
Replace GLANCE_USERNAME with a user name for Glance access, and replace
STORE_KEY and TEMP_URL_KEY with suitable keys.
Note: Do not use "--gen-secret" CLI parameter because it will cause the
"radosgw-admin" utility to generate keys with slash symbols which do not
work with Glance.
#. Configure Glance API service for RADOS Swift API as backend. Edit the #. Configure Glance API service for RADOS Swift API as backend. Edit the
configuration file for the Glance API service (is typically located at configuration file for the Glance API service (is typically located at
``/etc/glance/glance-api.conf``). Replace RADOS_IP and PORT with the IP/port ``/etc/glance/glance-api.conf``)::
of the RADOS Gateway API service::
[glance_store] [glance_store]
stores = file, http, swift stores = file, http, swift
default_store = swift default_store = swift
swift_store_auth_version = 1 default_swift_reference=ref1
swift_store_auth_address = http://RADOS_IP:PORT/auth/1.0 swift_store_config_file=/etc/glance/glance-swift-creds.conf
swift_store_user = GLANCE_USERNAME:swift
swift_store_key = STORE_KEY
swift_store_container = glance swift_store_container = glance
swift_store_create_container_on_put = True swift_store_create_container_on_put = True
In the file referenced in ``swift_store_config_file`` option, add the
following::
[ref1]
user = <service project>:<service user name>
key = <service user password>
user_domain_id = default
project_domain_id = default
auth_version = 3
auth_address = http://keystone.example.com/identity
Values for user and key options correspond to keystone credentials for
RADOS Gateway service user.
Note: RADOS Gateway uses FastCGI protocol for interacting with HTTP server. Note: RADOS Gateway uses FastCGI protocol for interacting with HTTP server.
Read your HTTP server documentation if you want to enable HTTPS support. Read your HTTP server documentation if you want to enable HTTPS support.
#. Restart Glance API service and upload all needed images. #. Restart Glance API service and upload all needed images.
#. Change Ironic configuration file on the conductor host(s) as follows:: #. If you're using custom container name in RADOS, change Ironic configuration
file on the conductor host(s) as follows::
[glance] [glance]
swift_container = glance swift_container = glance
swift_api_version = v1
swift_endpoint_url = http://RADOS_IP:PORT
swift_temp_url_key = TEMP_URL_KEY
[deploy]
object_store_endpoint_type = radosgw
#. Restart Ironic conductor service(s). #. Restart Ironic conductor service(s).

View File

@ -378,7 +378,6 @@ glance:
swift_temp_url_duration = 3600 swift_temp_url_duration = 3600
swift_temp_url_expected_download_start_delay = 0 swift_temp_url_expected_download_start_delay = 0
swift_temp_url_key = *** swift_temp_url_key = ***
temp_url_endpoint_type = swift
timeout = None timeout = None
ilo: ilo:

View File

@ -61,8 +61,8 @@ Configuration drive storage in an object store
Under normal circumstances, the configuration drive can be stored in the Under normal circumstances, the configuration drive can be stored in the
Bare Metal service when the size is less than 64KB. Optionally, if the size Bare Metal service when the size is less than 64KB. Optionally, if the size
is larger than 64KB there is support to store it in swift or radosgw backed is larger than 64KB there is support to store it in a swift endpoint. Both
object store. Both swift and radosgw use swift-style APIs. swift and radosgw use swift-style APIs.
The following option in ``/etc/ironic/ironic.conf`` enables swift as an object The following option in ``/etc/ironic/ironic.conf`` enables swift as an object
store backend to store config drive. This uses the Identity service to store backend to store config drive. This uses the Identity service to
@ -83,7 +83,6 @@ instead. ::
... ...
configdrive_use_object_store = True configdrive_use_object_store = True
object_store_endpoint_type = radosgw
[swift] [swift]
... ...

View File

@ -67,7 +67,6 @@ and Object Storage service as described below.
[glance] [glance]
temp_url_endpoint_type = swift
swift_endpoint_url = http://openstack/swift swift_endpoint_url = http://openstack/swift
swift_account = AUTH_bc39f1d9dcf9486899088007789ae643 swift_account = AUTH_bc39f1d9dcf9486899088007789ae643
swift_container = glance swift_container = glance

View File

@ -149,20 +149,6 @@ class GlanceImageService(base_image_service.BaseImageService,
endpoint_url = re.sub('/v1/AUTH_[^/]+/?$', '', endpoint_url) endpoint_url = re.sub('/v1/AUTH_[^/]+/?$', '', endpoint_url)
key = CONF.glance.swift_temp_url_key key = CONF.glance.swift_temp_url_key
if CONF.deploy.object_store_endpoint_type == 'radosgw':
chunks = urlparse.urlsplit(CONF.glance.swift_endpoint_url)
if not chunks.path:
endpoint_url = urlparse.urljoin(
endpoint_url, 'swift')
elif chunks.path != '/swift':
raise exc.InvalidParameterValue(
_('Swift endpoint URL should only contain scheme, '
'hostname, optional port and optional /swift path '
'without trailing slash; provided value is: %s')
% endpoint_url)
template = '/{api_version}/{container}/{object_id}'
else:
account = CONF.glance.swift_account account = CONF.glance.swift_account
if not account: if not account:
swift_session = swift.get_swift_session() swift_session = swift.get_swift_session()
@ -197,11 +183,6 @@ class GlanceImageService(base_image_service.BaseImageService,
def _validate_temp_url_config(self): def _validate_temp_url_config(self):
"""Validate the required settings for a temporary URL.""" """Validate the required settings for a temporary URL."""
if (not CONF.glance.swift_temp_url_key
and CONF.deploy.object_store_endpoint_type != 'swift'):
raise exc.MissingParameterValue(_(
'Swift temporary URLs require a shared secret to be created. '
'You must provide "swift_temp_url_key" as a config option.'))
if (CONF.glance.swift_temp_url_duration if (CONF.glance.swift_temp_url_duration
< CONF.glance.swift_temp_url_expected_download_start_delay): < CONF.glance.swift_temp_url_expected_download_start_delay):
raise exc.InvalidParameterValue(_( raise exc.InvalidParameterValue(_(

View File

@ -44,17 +44,12 @@ class SwiftAPI(object):
"""Underlying Swift connection object.""" """Underlying Swift connection object."""
def __init__(self): def __init__(self):
"""Initialize the connection with swift or radosgw """Initialize the connection with swift
:raises: ConfigInvalid if required keystone authorization credentials :raises: ConfigInvalid if required keystone authorization credentials
with swift are missing. with swift are missing.
""" """
params = {'retries': CONF.swift.swift_max_retries} params = {'retries': CONF.swift.swift_max_retries}
if CONF.deploy.object_store_endpoint_type == 'radosgw':
params.update({'authurl': CONF.swift.auth_url,
'user': CONF.swift.username,
'key': CONF.swift.password})
else:
# NOTE(pas-ha) swiftclient still (as of 3.3.0) does not use # NOTE(pas-ha) swiftclient still (as of 3.3.0) does not use
# (adapter-based) SessionClient, and uses the passed in session # (adapter-based) SessionClient, and uses the passed in session
# only to resolve endpoint and get a token, # only to resolve endpoint and get a token,
@ -69,8 +64,7 @@ class SwiftAPI(object):
# with service auth # with service auth
params['session'] = session = get_swift_session() params['session'] = session = get_swift_session()
adapter = keystone.get_adapter('swift', session=session) adapter = keystone.get_adapter('swift', session=session)
params['os_options'] = { params['os_options'] = {'object_storage_url': adapter.get_endpoint()}
'object_storage_url': adapter.get_endpoint()}
# deconstruct back session-related options # deconstruct back session-related options
params['timeout'] = session.timeout params['timeout'] = session.timeout
if session.verify is False: if session.verify is False:

View File

@ -86,8 +86,6 @@ class BaseConductorManager(object):
:raises: DriverLoadError if an enabled driver cannot be loaded. :raises: DriverLoadError if an enabled driver cannot be loaded.
:raises: DriverNameConflict if a classic driver and a dynamic driver :raises: DriverNameConflict if a classic driver and a dynamic driver
are both enabled and have the same name. are both enabled and have the same name.
:raises: ConfigInvalid if required config options for connection with
radosgw are missing while storing config drive.
""" """
if self._started: if self._started:
raise RuntimeError(_('Attempt to start an already running ' raise RuntimeError(_('Attempt to start an already running '
@ -139,18 +137,6 @@ class BaseConductorManager(object):
self._collect_periodic_tasks(admin_context) self._collect_periodic_tasks(admin_context)
# Check for required config options if object_store_endpoint_type is
# radosgw
if (CONF.deploy.configdrive_use_object_store
and CONF.deploy.object_store_endpoint_type == "radosgw"):
if (None in (CONF.swift.auth_url, CONF.swift.username,
CONF.swift.password)):
msg = _("Parameters missing to make a connection with "
"radosgw. Ensure that [swift]/auth_url, "
"[swift]/username, and [swift]/password are all "
"configured.")
raise exception.ConfigInvalid(msg)
# clear all target_power_state with locks by this conductor # clear all target_power_state with locks by this conductor
self.dbapi.clear_node_target_power_state(self.host) self.dbapi.clear_node_target_power_state(self.host)
# clear all locks held by this conductor before registering # clear all locks held by this conductor before registering

View File

@ -3340,14 +3340,14 @@ def _get_configdrive_obj_name(node):
def _store_configdrive(node, configdrive): def _store_configdrive(node, configdrive):
"""Handle the storage of the config drive. """Handle the storage of the config drive.
If configured, the config drive data are uploaded to swift or radosgw. If configured, the config drive data are uploaded to a swift endpoint.
The Node's instance_info is updated to include either the temporary The Node's instance_info is updated to include either the temporary
Swift URL from the upload, or if no upload, the actual config drive data. Swift URL from the upload, or if no upload, the actual config drive data.
:param node: an Ironic node object. :param node: an Ironic node object.
:param configdrive: A gzipped and base64 encoded configdrive. :param configdrive: A gzipped and base64 encoded configdrive.
:raises: SwiftOperationError if an error occur when uploading the :raises: SwiftOperationError if an error occur when uploading the
config drive to swift or radosgw. config drive to the swift endpoint.
:raises: ConfigInvalid if required keystone authorization credentials :raises: ConfigInvalid if required keystone authorization credentials
with swift are missing. with swift are missing.

View File

@ -95,15 +95,7 @@ opts = [
deprecated_name='configdrive_use_swift', deprecated_name='configdrive_use_swift',
help=_('Whether to upload the config drive to object store. ' help=_('Whether to upload the config drive to object store. '
'Set this option to True to store config drive ' 'Set this option to True to store config drive '
'in swift or radosgw.')), 'in a swift endpoint.')),
cfg.StrOpt('object_store_endpoint_type',
default='swift',
deprecated_group='glance',
deprecated_name='temp_url_endpoint_type',
choices=[('swift', _('use Object Storage service')),
('radosgw', _('use RADOS object store'))],
help=_('Type of object store endpoint type to be '
'used as a backend')),
] ]

View File

@ -68,7 +68,7 @@ opts = [
'swift_endpoint_url', 'swift_endpoint_url',
help=_('The "endpoint" (scheme, hostname, optional port) for ' help=_('The "endpoint" (scheme, hostname, optional port) for '
'the Swift URL of the form ' 'the Swift URL of the form '
'"endpoint_url/api_version/[account/]container/object_id". ' '"endpoint_url/api_version/account/container/object_id". '
'Do not include trailing "/". ' 'Do not include trailing "/". '
'For example, use "https://swift.example.com". If using RADOS ' 'For example, use "https://swift.example.com". If using RADOS '
'Gateway, endpoint may also contain /swift path; if it does ' 'Gateway, endpoint may also contain /swift path; if it does '
@ -79,7 +79,7 @@ opts = [
default='v1', default='v1',
help=_('The Swift API version to create a temporary URL for. ' help=_('The Swift API version to create a temporary URL for. '
'Defaults to "v1". Swift temporary URL format: ' 'Defaults to "v1". Swift temporary URL format: '
'"endpoint_url/api_version/[account/]container/object_id"')), '"endpoint_url/api_version/account/container/object_id"')),
cfg.StrOpt( cfg.StrOpt(
'swift_account', 'swift_account',
help=_('The account that Glance uses to communicate with ' help=_('The account that Glance uses to communicate with '
@ -89,7 +89,7 @@ opts = [
'If not set, the default value is calculated based on the ID ' 'If not set, the default value is calculated based on the ID '
'of the project used to access Swift (as set in the [swift] ' 'of the project used to access Swift (as set in the [swift] '
'section). Swift temporary URL format: ' 'section). Swift temporary URL format: '
'"endpoint_url/api_version/[account/]container/object_id"')), '"endpoint_url/api_version/account/container/object_id"')),
cfg.StrOpt( cfg.StrOpt(
'swift_container', 'swift_container',
default='glance', default='glance',
@ -97,7 +97,7 @@ opts = [
'images in. Defaults to "glance", which is the default ' 'images in. Defaults to "glance", which is the default '
'in glance-api.conf. ' 'in glance-api.conf. '
'Swift temporary URL format: ' 'Swift temporary URL format: '
'"endpoint_url/api_version/[account/]container/object_id"')), '"endpoint_url/api_version/account/container/object_id"')),
cfg.IntOpt('swift_store_multiple_containers_seed', cfg.IntOpt('swift_store_multiple_containers_seed',
default=0, default=0,
help=_('This should match a config by the same name in the ' help=_('This should match a config by the same name in the '

View File

@ -23,7 +23,6 @@ from keystoneauth1 import loading as kaloading
import mock import mock
from oslo_config import cfg from oslo_config import cfg
from oslo_utils import uuidutils from oslo_utils import uuidutils
from six.moves.urllib import parse as urlparse
import testtools import testtools
from ironic.common import context from ironic.common import context
@ -685,65 +684,6 @@ class TestGlanceSwiftTempURL(base.TestCase):
self.service.swift_temp_url, image_info) self.service.swift_temp_url, image_info)
self.assertFalse(tempurl_mock.called) self.assertFalse(tempurl_mock.called)
@mock.patch('swiftclient.utils.generate_temp_url', autospec=True)
def test_swift_temp_url_radosgw(self, tempurl_mock):
self.config(object_store_endpoint_type='radosgw', group='deploy')
path = ('/v1'
'/glance'
'/757274c4-2856-4bd2-bb20-9a4a231e187b')
tempurl_mock.return_value = (
path + '?temp_url_sig=hmacsig&temp_url_expires=1400001200')
self.service._validate_temp_url_config = mock.Mock()
temp_url = self.service.swift_temp_url(image_info=self.fake_image)
self.assertEqual(
(urlparse.urljoin(CONF.glance.swift_endpoint_url, 'swift')
+ tempurl_mock.return_value),
temp_url)
tempurl_mock.assert_called_with(
path=path,
seconds=CONF.glance.swift_temp_url_duration,
key=CONF.glance.swift_temp_url_key,
method='GET')
@mock.patch('swiftclient.utils.generate_temp_url', autospec=True)
def test_swift_temp_url_radosgw_endpoint_with_swift(self, tempurl_mock):
self.config(swift_endpoint_url='https://swift.radosgw.com/swift',
group='glance')
self.config(object_store_endpoint_type='radosgw', group='deploy')
path = ('/v1'
'/glance'
'/757274c4-2856-4bd2-bb20-9a4a231e187b')
tempurl_mock.return_value = (
path + '?temp_url_sig=hmacsig&temp_url_expires=1400001200')
self.service._validate_temp_url_config = mock.Mock()
temp_url = self.service.swift_temp_url(image_info=self.fake_image)
self.assertEqual(
CONF.glance.swift_endpoint_url + tempurl_mock.return_value,
temp_url)
tempurl_mock.assert_called_with(
path=path,
seconds=CONF.glance.swift_temp_url_duration,
key=CONF.glance.swift_temp_url_key,
method='GET')
@mock.patch('swiftclient.utils.generate_temp_url', autospec=True)
def test_swift_temp_url_radosgw_endpoint_invalid(self, tempurl_mock):
self.config(swift_endpoint_url='https://swift.radosgw.com/eggs/',
group='glance')
self.config(object_store_endpoint_type='radosgw', group='deploy')
self.service._validate_temp_url_config = mock.Mock()
self.assertRaises(exception.InvalidParameterValue,
self.service.swift_temp_url,
self.fake_image)
self.assertFalse(tempurl_mock.called)
@mock.patch('swiftclient.utils.generate_temp_url', autospec=True) @mock.patch('swiftclient.utils.generate_temp_url', autospec=True)
def test_swift_temp_url_multiple_containers(self, tempurl_mock): def test_swift_temp_url_multiple_containers(self, tempurl_mock):
@ -777,20 +717,8 @@ class TestGlanceSwiftTempURL(base.TestCase):
def test__validate_temp_url_config(self): def test__validate_temp_url_config(self):
self.service._validate_temp_url_config() self.service._validate_temp_url_config()
def test__validate_temp_url_key_no_exception(self): def test__validate_temp_url_no_key_no_exception(self):
self.config(swift_temp_url_key=None, group='glance') self.config(swift_temp_url_key=None, group='glance')
self.config(object_store_endpoint_type='swift', group='deploy')
self.service._validate_temp_url_config()
def test__validate_temp_url_key_exception(self):
self.config(swift_temp_url_key=None, group='glance')
self.config(object_store_endpoint_type='radosgw', group='deploy')
self.assertRaises(exception.MissingParameterValue,
self.service._validate_temp_url_config)
def test__validate_temp_url_no_account_exception_radosgw(self):
self.config(swift_account=None, group='glance')
self.config(object_store_endpoint_type='radosgw', group='deploy')
self.service._validate_temp_url_config() self.service._validate_temp_url_config()
def test__validate_temp_url_endpoint_less_than_download_delay(self): def test__validate_temp_url_endpoint_less_than_download_delay(self):

View File

@ -57,30 +57,6 @@ class SwiftTestCase(base.TestCase):
os_options={'object_storage_url': 'http://example.com/objects'} os_options={'object_storage_url': 'http://example.com/objects'}
) )
def test___init___radosgw(self, connection_mock, swift_session_mock):
"""Check if client is properly initialized with radosgw"""
auth_url = 'http://1.2.3.4'
username = 'foo'
password = 'foo_password'
CONF.set_override('object_store_endpoint_type', 'radosgw',
group='deploy')
opts = [cfg.StrOpt('auth_url'), cfg.StrOpt('username'),
cfg.StrOpt('password')]
CONF.register_opts(opts, group='swift')
CONF.set_override('auth_url', auth_url, group='swift')
CONF.set_override('username', username, group='swift')
CONF.set_override('password', password, group='swift')
swift.SwiftAPI()
params = {'authurl': auth_url,
'user': username,
'key': password,
'retries': 2}
connection_mock.assert_called_once_with(**params)
self.assertFalse(swift_session_mock.called)
@mock.patch.object(__builtin__, 'open', autospec=True) @mock.patch.object(__builtin__, 'open', autospec=True)
def test_create_object(self, open_mock, connection_mock, keystone_mock): def test_create_object(self, open_mock, connection_mock, keystone_mock):
swiftapi = swift.SwiftAPI() swiftapi = swift.SwiftAPI()

View File

@ -218,28 +218,6 @@ class StartStopTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
self.service.del_host() self.service.del_host()
self.assertTrue(wait_mock.called) self.assertTrue(wait_mock.called)
def test_start_fails_on_missing_config_for_configdrive(self):
"""Check to fail conductor on missing config options"""
missing_parameters_error = ("Parameters missing to make a "
"connection with radosgw")
CONF.set_override('configdrive_use_object_store', True,
group='deploy')
CONF.set_override('object_store_endpoint_type', 'radosgw',
group='deploy')
params = {'auth_url': 'http://1.2.3.4',
'username': 'foo', 'password': 'foo_pass'}
CONF.register_opts((cfg.StrOpt(x) for x in params),
group='swift')
for key, value in params.items():
test_params = params.copy()
test_params[key] = None
for test_key, test_value in test_params.items():
CONF.set_override(key, test_value, group='swift')
with self.assertRaisesRegex(exception.ConfigInvalid,
missing_parameters_error):
self._start_service()
def test_conductor_shutdown_flag(self): def test_conductor_shutdown_flag(self):
self._start_service() self._start_service()
self.assertFalse(self.service._shutdown) self.assertFalse(self.service._shutdown)

View File

@ -0,0 +1,9 @@
---
upgrade:
- |
The ``swift/endpoint_type`` configuration option is now removed.
python-swiftclient 3.2.0 (Ocata) and above removed support for the native
URL type used by radosgw. Since using a ``swift/endpoint_type`` value of
``radosgw`` would fail anyway, it is removed. Deployers must now configure
ceph with ``rgw swift account in url = True``. This must be set before
upgrading to this release.