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 glance
|
||||||
from nova.conf import guestfs
|
from nova.conf import guestfs
|
||||||
from nova.conf import hyperv
|
from nova.conf import hyperv
|
||||||
from nova.conf import image_file_url
|
|
||||||
from nova.conf import ipv6
|
from nova.conf import ipv6
|
||||||
from nova.conf import ironic
|
from nova.conf import ironic
|
||||||
from nova.conf import key_manager
|
from nova.conf import key_manager
|
||||||
@ -99,7 +98,6 @@ glance.register_opts(CONF)
|
|||||||
guestfs.register_opts(CONF)
|
guestfs.register_opts(CONF)
|
||||||
hyperv.register_opts(CONF)
|
hyperv.register_opts(CONF)
|
||||||
mks.register_opts(CONF)
|
mks.register_opts(CONF)
|
||||||
image_file_url.register_opts(CONF)
|
|
||||||
ipv6.register_opts(CONF)
|
ipv6.register_opts(CONF)
|
||||||
ironic.register_opts(CONF)
|
ironic.register_opts(CONF)
|
||||||
key_manager.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``
|
@ -44,8 +44,6 @@ oslo.policy.policies =
|
|||||||
nova.compute.monitors.cpu =
|
nova.compute.monitors.cpu =
|
||||||
virt_driver = nova.compute.monitors.cpu.virt_driver:Monitor
|
virt_driver = nova.compute.monitors.cpu.virt_driver:Monitor
|
||||||
|
|
||||||
nova.image.download.modules =
|
|
||||||
file = nova.image.download.file
|
|
||||||
console_scripts =
|
console_scripts =
|
||||||
nova-all = nova.cmd.all:main
|
nova-all = nova.cmd.all:main
|
||||||
nova-api = nova.cmd.api:main
|
nova-api = nova.cmd.api:main
|
||||||
|
Loading…
x
Reference in New Issue
Block a user