conf: remove deprecated image url options
Change-Id: I7687cc89545a7a8b295dd6535b4ccebc913a2e0e Implements: blueprint centralize-config-options-pike
This commit is contained in:
parent
fb693f07f0
commit
ff8dcf6dcd
@ -41,7 +41,6 @@ from nova.conf import floating_ips
|
||||
from nova.conf import glance
|
||||
from nova.conf import guestfs
|
||||
from nova.conf import hyperv
|
||||
from nova.conf import image_file_url
|
||||
from nova.conf import ipv6
|
||||
from nova.conf import ironic
|
||||
from nova.conf import key_manager
|
||||
@ -99,7 +98,6 @@ glance.register_opts(CONF)
|
||||
guestfs.register_opts(CONF)
|
||||
hyperv.register_opts(CONF)
|
||||
mks.register_opts(CONF)
|
||||
image_file_url.register_opts(CONF)
|
||||
ipv6.register_opts(CONF)
|
||||
ironic.register_opts(CONF)
|
||||
key_manager.register_opts(CONF)
|
||||
|
@ -1,84 +0,0 @@
|
||||
# Copyright 2013 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 oslo_config import cfg
|
||||
|
||||
|
||||
image_file_url_group = cfg.OptGroup(
|
||||
'image_file_url',
|
||||
title='Image File URL Options')
|
||||
|
||||
filesystems = cfg.ListOpt(
|
||||
name='filesystems',
|
||||
default=[],
|
||||
deprecated_for_removal=True,
|
||||
deprecated_since="14.0.0",
|
||||
deprecated_reason="""
|
||||
The feature to download images from glance via filesystem is not used and will
|
||||
be removed in the future.
|
||||
""",
|
||||
help="""
|
||||
List of file systems that are configured in this file in the
|
||||
image_file_url:<list entry name> sections
|
||||
""")
|
||||
|
||||
# NOTE(jbresnah) because the group under which these options are added is
|
||||
# dynamically determined these options need to stay out of global space
|
||||
# or they will confuse generate_sample.sh
|
||||
filesystem_opts = [
|
||||
cfg.StrOpt('id',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_since="14.0.0",
|
||||
deprecated_reason="""
|
||||
The feature to download images from glance via filesystem is not used and will
|
||||
be removed in the future.
|
||||
""",
|
||||
help="""
|
||||
A unique ID given to each file system. This is value is set in Glance and
|
||||
agreed upon here so that the operator knowns they are dealing with the same
|
||||
file system.
|
||||
"""),
|
||||
cfg.StrOpt('mountpoint',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_since="14.0.0",
|
||||
deprecated_reason="""
|
||||
The feature to download images from glance via filesystem is not used and will
|
||||
be removed in the future.
|
||||
""",
|
||||
help="""
|
||||
The path at which the file system is mounted.
|
||||
"""),
|
||||
]
|
||||
|
||||
ALL_OPTS = [filesystems]
|
||||
|
||||
|
||||
def register_opts(conf):
|
||||
conf.register_group(image_file_url_group)
|
||||
conf.register_opts(ALL_OPTS, group=image_file_url_group)
|
||||
for fs in conf.image_file_url.filesystems:
|
||||
group_name = 'image_file_url:' + fs
|
||||
conf.register_opts(filesystem_opts, group=group_name)
|
||||
|
||||
|
||||
def list_opts():
|
||||
# NOTE(markus_z): As the "filesystem" opt has an empty list as a default
|
||||
# value and this value is necessary for a correct group name, we cannot
|
||||
# list the "filesystem_opts" for the "nova.conf.sample" file here. A
|
||||
# follow up patch will deprecate those. Due to their dynamic creation
|
||||
# they never got shown in "nova.conf.sample" nor the config reference
|
||||
# manual. I see no need to change this here with a dummy group or something
|
||||
# like that.
|
||||
return {image_file_url_group: ALL_OPTS}
|
@ -1,23 +0,0 @@
|
||||
# Copyright 2013 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 nova import exception
|
||||
|
||||
|
||||
class TransferBase(object):
|
||||
|
||||
def download(self, context, url_parts, dst_path, metadata, **kwargs):
|
||||
raise exception.ImageDownloadModuleNotImplementedError(
|
||||
method_name='download')
|
@ -1,145 +0,0 @@
|
||||
# Copyright 2013 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 oslo_log import log as logging
|
||||
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
from nova.i18n import _, _LI
|
||||
import nova.image.download.base as xfer_base
|
||||
import nova.virt.libvirt.utils as lv_utils
|
||||
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# This module extends the configuration options for nova.conf. If the user
|
||||
# wishes to use the specific configuration settings the following needs to
|
||||
# be added to nova.conf:
|
||||
# [image_file_url]
|
||||
# filesystem = <a list of strings referencing a config section>
|
||||
#
|
||||
# For each entry in the filesystem list a new configuration section must be
|
||||
# added with the following format:
|
||||
# [image_file_url:<list entry>]
|
||||
# id = <string>
|
||||
# mountpoint = <string>
|
||||
#
|
||||
# id:
|
||||
# An opaque string. In order for this module to know that the remote
|
||||
# FS is the same one that is mounted locally it must share information
|
||||
# with the glance deployment. Both glance and nova-compute must be
|
||||
# configured with a unique matching string. This ensures that the
|
||||
# file:// advertised URL is describing a file system that is known
|
||||
# to nova-compute
|
||||
# mountpoint:
|
||||
# The location at which the file system is locally mounted. Glance
|
||||
# may mount a shared file system on a different path than nova-compute.
|
||||
# This value will be compared against the metadata advertised with
|
||||
# glance and paths will be adjusted to ensure that the correct file
|
||||
# file is copied.
|
||||
#
|
||||
# If these values are not added to nova.conf and the file module is in the
|
||||
# allowed_direct_url_schemes list, then the legacy behavior will occur such
|
||||
# that a copy will be attempted assuming that the glance and nova file systems
|
||||
# are the same.
|
||||
|
||||
|
||||
class FileTransfer(xfer_base.TransferBase):
|
||||
|
||||
desc_required_keys = ['id', 'mountpoint']
|
||||
|
||||
def _get_options(self):
|
||||
fs_dict = {}
|
||||
for fs in CONF.image_file_url.filesystems:
|
||||
group_name = 'image_file_url:' + fs
|
||||
conf_group = CONF[group_name]
|
||||
if conf_group.id is None:
|
||||
msg = _('The group %(group_name)s must be configured with '
|
||||
'an id.') % {'group_name': group_name}
|
||||
raise exception.ImageDownloadModuleConfigurationError(
|
||||
module=str(self), reason=msg)
|
||||
fs_dict[CONF[group_name].id] = CONF[group_name]
|
||||
return fs_dict
|
||||
|
||||
def _verify_config(self):
|
||||
for fs_key in self.filesystems:
|
||||
for r in self.desc_required_keys:
|
||||
fs_ent = self.filesystems[fs_key]
|
||||
if fs_ent[r] is None:
|
||||
msg = _('The key %s is required in all file system '
|
||||
'descriptions.')
|
||||
LOG.error(msg)
|
||||
raise exception.ImageDownloadModuleConfigurationError(
|
||||
module=str(self), reason=msg)
|
||||
|
||||
def _file_system_lookup(self, metadata, url_parts):
|
||||
for r in self.desc_required_keys:
|
||||
if r not in metadata:
|
||||
url = url_parts.geturl()
|
||||
msg = _('The key %(r)s is required in the location metadata '
|
||||
'to access the url %(url)s.') % {'r': r, 'url': url}
|
||||
LOG.info(msg)
|
||||
raise exception.ImageDownloadModuleMetaDataError(
|
||||
module=str(self), reason=msg)
|
||||
id = metadata['id']
|
||||
if id not in self.filesystems:
|
||||
LOG.info(_LI('The ID %(id)s is unknown.'), {'id': id})
|
||||
return
|
||||
fs_descriptor = self.filesystems[id]
|
||||
return fs_descriptor
|
||||
|
||||
def _normalize_destination(self, nova_mount, glance_mount, path):
|
||||
if not path.startswith(glance_mount):
|
||||
msg = (_('The mount point advertised by glance: %(glance_mount)s, '
|
||||
'does not match the URL path: %(path)s') %
|
||||
{'glance_mount': glance_mount, 'path': path})
|
||||
raise exception.ImageDownloadModuleMetaDataError(
|
||||
module=str(self), reason=msg)
|
||||
new_path = path.replace(glance_mount, nova_mount, 1)
|
||||
return new_path
|
||||
|
||||
def download(self, context, url_parts, dst_file, metadata, **kwargs):
|
||||
self.filesystems = self._get_options()
|
||||
if not self.filesystems:
|
||||
# NOTE(jbresnah) when nothing is configured assume legacy behavior
|
||||
nova_mountpoint = '/'
|
||||
glance_mountpoint = '/'
|
||||
else:
|
||||
self._verify_config()
|
||||
fs_descriptor = self._file_system_lookup(metadata, url_parts)
|
||||
if fs_descriptor is None:
|
||||
msg = (_('No matching ID for the URL %s was found.') %
|
||||
url_parts.geturl())
|
||||
raise exception.ImageDownloadModuleError(reason=msg,
|
||||
module=str(self))
|
||||
nova_mountpoint = fs_descriptor['mountpoint']
|
||||
glance_mountpoint = metadata['mountpoint']
|
||||
|
||||
source_file = self._normalize_destination(nova_mountpoint,
|
||||
glance_mountpoint,
|
||||
url_parts.path)
|
||||
lv_utils.copy_image(source_file, dst_file)
|
||||
LOG.info(_LI('Copied %(source_file)s using %(module_str)s'),
|
||||
{'source_file': source_file, 'module_str': str(self)})
|
||||
|
||||
|
||||
def get_download_handler(**kwargs):
|
||||
return FileTransfer()
|
||||
|
||||
|
||||
def get_schemes():
|
||||
return ['file', 'filesystem']
|
@ -1,110 +0,0 @@
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
import mock
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
from nova.image.download import file as tm_file
|
||||
from nova import test
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
|
||||
|
||||
class TestFileTransferModule(test.NoDBTestCase):
|
||||
|
||||
@mock.patch('nova.virt.libvirt.utils.copy_image')
|
||||
def test_filesystem_success(self, copy_mock):
|
||||
self.flags(allowed_direct_url_schemes=['file'], group='glance')
|
||||
self.flags(group='image_file_url', filesystems=['gluster'])
|
||||
# register opts for dynamically created group 'image_file_url:gluster'
|
||||
nova.conf.image_file_url.register_opts(CONF)
|
||||
|
||||
mountpoint = '/gluster'
|
||||
url = 'file:///gluster/my/image/path'
|
||||
url_parts = urlparse.urlparse(url)
|
||||
fs_id = 'someid'
|
||||
loc_meta = {
|
||||
'id': fs_id,
|
||||
'mountpoint': mountpoint
|
||||
}
|
||||
dst_file = mock.MagicMock()
|
||||
|
||||
tm = tm_file.FileTransfer()
|
||||
|
||||
# NOTE(Jbresnah) The following options must be added after the module
|
||||
# has added the specific groups.
|
||||
self.flags(group='image_file_url:gluster', id=fs_id)
|
||||
self.flags(group='image_file_url:gluster', mountpoint=mountpoint)
|
||||
|
||||
tm.download(mock.sentinel.ctx, url_parts, dst_file, loc_meta)
|
||||
copy_mock.assert_called_once_with('/gluster/my/image/path', dst_file)
|
||||
|
||||
@mock.patch('nova.virt.libvirt.utils.copy_image')
|
||||
def test_filesystem_mismatched_mountpoint(self, copy_mock):
|
||||
self.flags(allowed_direct_url_schemes=['file'], group='glance')
|
||||
self.flags(group='image_file_url', filesystems=['gluster'])
|
||||
# register opts for dynamically created group 'image_file_url:gluster'
|
||||
nova.conf.image_file_url.register_opts(CONF)
|
||||
|
||||
mountpoint = '/gluster'
|
||||
# Should include the mountpoint before my/image/path
|
||||
url = 'file:///my/image/path'
|
||||
url_parts = urlparse.urlparse(url)
|
||||
fs_id = 'someid'
|
||||
loc_meta = {
|
||||
'id': fs_id,
|
||||
'mountpoint': mountpoint
|
||||
}
|
||||
dst_file = mock.MagicMock()
|
||||
|
||||
tm = tm_file.FileTransfer()
|
||||
|
||||
self.flags(group='image_file_url:gluster', id=fs_id)
|
||||
self.flags(group='image_file_url:gluster', mountpoint=mountpoint)
|
||||
|
||||
self.assertRaises(exception.ImageDownloadModuleMetaDataError,
|
||||
tm.download, mock.sentinel.ctx, url_parts,
|
||||
dst_file, loc_meta)
|
||||
self.assertFalse(copy_mock.called)
|
||||
|
||||
@mock.patch('nova.virt.libvirt.utils.copy_image')
|
||||
def test_filesystem_mismatched_filesystem(self, copy_mock):
|
||||
self.flags(allowed_direct_url_schemes=['file'], group='glance')
|
||||
self.flags(group='image_file_url', filesystems=['gluster'])
|
||||
# register opts for dynamically created group 'image_file_url:gluster'
|
||||
nova.conf.image_file_url.register_opts(CONF)
|
||||
|
||||
mountpoint = '/gluster'
|
||||
# Should include the mountpoint before my/image/path
|
||||
url = 'file:///my/image/path'
|
||||
url_parts = urlparse.urlparse(url)
|
||||
fs_id = 'someid'
|
||||
loc_meta = {
|
||||
'id': 'funky',
|
||||
'mountpoint': mountpoint
|
||||
}
|
||||
dst_file = mock.MagicMock()
|
||||
|
||||
tm = tm_file.FileTransfer()
|
||||
|
||||
self.flags(group='image_file_url:gluster', id=fs_id)
|
||||
self.flags(group='image_file_url:gluster', mountpoint=mountpoint)
|
||||
|
||||
self.assertRaises(exception.ImageDownloadModuleError,
|
||||
tm.download, mock.sentinel.ctx, url_parts,
|
||||
dst_file, loc_meta)
|
||||
self.assertFalse(copy_mock.called)
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
Configuration options related to image file have been removed. They were
|
||||
marked as deprecated because the feature to download images from glance
|
||||
via filesystem is not used. Below are the removed options:
|
||||
|
||||
- ``image_file_url.filesystems``
|
||||
- ``image_file_url.FS.id``
|
||||
- ``image_file_url.FS.mountpoint``
|
Loading…
Reference in New Issue
Block a user