diff --git a/nova/conf/xenserver.py b/nova/conf/xenserver.py index a6936a1c44d3..15eabd6434e9 100644 --- a/nova/conf/xenserver.py +++ b/nova/conf/xenserver.py @@ -159,99 +159,6 @@ session, which allows you to make concurrent XenAPI connections. ] -xenapi_torrent_opts = [ - cfg.StrOpt('torrent_base_url', - deprecated_for_removal=True, - deprecated_since='15.0.0', - deprecated_reason=""" -The torrent feature has not been tested nor maintained, and as such is being -removed. -""", - help=""" -Base URL for torrent files; must contain a slash character (see RFC 1808, -step 6). -"""), - cfg.FloatOpt('torrent_seed_chance', - default=1.0, - min=0, - deprecated_for_removal=True, - deprecated_since='15.0.0', - deprecated_reason=""" -The torrent feature has not been tested nor maintained, and as such is being -removed. -""", - help='Probability that peer will become a seeder (1.0 = 100%)'), - cfg.IntOpt('torrent_seed_duration', - default=3600, - deprecated_for_removal=True, - deprecated_since='15.0.0', - deprecated_reason=""" -The torrent feature has not been tested nor maintained, and as such is being -removed. -""", - help=""" -Number of seconds after downloading an image via BitTorrent that it should -be seeded for other peers.' -"""), - cfg.IntOpt('torrent_max_last_accessed', - default=86400, - min=0, - deprecated_for_removal=True, - deprecated_since='15.0.0', - deprecated_reason=""" -The torrent feature has not been tested nor maintained, and as such is being -removed. -""", - help=""" -Cached torrent files not accessed within this number of seconds can be reaped. -"""), - cfg.PortOpt('torrent_listen_port_start', - default=6881, - deprecated_for_removal=True, - deprecated_since='15.0.0', - deprecated_reason=""" -The torrent feature has not been tested nor maintained, and as such is being -removed. -""", - help='Beginning of port range to listen on'), - cfg.PortOpt('torrent_listen_port_end', - default=6891, - deprecated_for_removal=True, - deprecated_since='15.0.0', - deprecated_reason=""" -The torrent feature has not been tested nor maintained, and as such is being -removed. -""", - help='End of port range to listen on'), - cfg.IntOpt('torrent_download_stall_cutoff', - default=600, - min=0, - deprecated_for_removal=True, - deprecated_since='15.0.0', - deprecated_reason=""" -The torrent feature has not been tested nor maintained, and as such is being -removed. -""", - help=""" -Number of seconds a download can remain at the same progress percentage w/o -being considered a stall. -"""), - cfg.IntOpt('torrent_max_seeder_processes_per_host', - default=1, - min=-1, - deprecated_for_removal=True, - deprecated_since='15.0.0', - deprecated_reason=""" -The torrent feature has not been tested nor maintained, and as such is being -removed. -""", - help=""" -Maximum number of seeder processes to run concurrently within a given dom0 -(-1 = no limit). -""") -] - - xenapi_vm_utils_opts = [ cfg.StrOpt('cache_images', default='all', @@ -331,22 +238,6 @@ considerably since large runs of zeros won't have to be rsynced. help=""" Maximum number of retries to unplug VBD. If set to 0, should try once, no retries. -"""), - cfg.StrOpt('torrent_images', - default='none', - choices=('all', 'some', 'none'), - help=""" -Whether or not to download images via Bit Torrent. - -The value for this option must be chosen from the choices listed -here. Configuring a value other than these will default to 'none'. - -Possible values: - -* `all`: will download all images. -* `some`: will only download images that have the image_property - `bittorrent=true`. -* `none`: will turnoff downloading images via Bit Torrent. """), cfg.StrOpt('ipxe_network_name', help=""" @@ -661,7 +552,6 @@ Possible values: ALL_XENSERVER_OPTS = (xenapi_agent_opts + xenapi_session_opts + - xenapi_torrent_opts + xenapi_vm_utils_opts + xenapi_opts + xenapi_vmops_opts + diff --git a/nova/tests/unit/virt/xenapi/image/test_bittorrent.py b/nova/tests/unit/virt/xenapi/image/test_bittorrent.py deleted file mode 100644 index 535e9d804ec5..000000000000 --- a/nova/tests/unit/virt/xenapi/image/test_bittorrent.py +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# 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 -from os_xenapi import client -import six - -from nova import context -from nova import test -from nova.tests.unit.virt.xenapi import stubs -from nova.virt.xenapi import driver as xenapi_conn -from nova.virt.xenapi import fake -from nova.virt.xenapi.image import bittorrent - - -class TestBittorrentStore(stubs.XenAPITestBaseNoDB): - def setUp(self): - super(TestBittorrentStore, self).setUp() - self.store = bittorrent.BittorrentStore() - - self.flags(torrent_base_url='http://foo', - connection_url='test_url', - connection_password='test_pass', - group='xenserver') - - self.context = context.RequestContext( - 'user', 'project', auth_token='foobar') - - fake.reset() - stubs.stubout_session(self.stubs, fake.SessionBase) - - driver = xenapi_conn.XenAPIDriver(False) - self.session = driver._session - - self.stub_out('nova.virt.xenapi.vm_utils.get_sr_path', - lambda *a, **kw: '/fake/sr/path') - - @mock.patch.object(client.session.XenAPISession, 'call_plugin_serialized') - def test_download_image(self, mock_call_plugin): - - instance = {'uuid': '00000000-0000-0000-0000-000000007357'} - params = {'image_id': 'fake_image_uuid', - 'sr_path': '/fake/sr/path', - 'torrent_download_stall_cutoff': 600, - 'torrent_listen_port_end': 6891, - 'torrent_listen_port_start': 6881, - 'torrent_max_last_accessed': 86400, - 'torrent_max_seeder_processes_per_host': 1, - 'torrent_seed_chance': 1.0, - 'torrent_seed_duration': 3600, - 'torrent_url': 'http://foo/fake_image_uuid.torrent', - 'uuid_stack': ['uuid1']} - - self.stub_out('nova.virt.xenapi.vm_utils._make_uuid_stack', - lambda *a, **kw: ['uuid1']) - - self.store.download_image(self.context, self.session, - instance, 'fake_image_uuid') - - mock_call_plugin.assert_called_once_with('bittorrent.py', - 'download_vhd', **params) - - def test_upload_image(self): - self.assertRaises(NotImplementedError, self.store.upload_image, - self.context, self.session, mock.ANY, 'fake_image_uuid', - ['fake_vdi_uuid']) - - -class LookupTorrentURLTestCase(test.NoDBTestCase): - def setUp(self): - super(LookupTorrentURLTestCase, self).setUp() - self.store = bittorrent.BittorrentStore() - self.image_id = 'fakeimageid' - - def test_default_fetch_url_no_base_url_set(self): - self.flags(torrent_base_url=None, - group='xenserver') - - exc = self.assertRaises( - RuntimeError, self.store._lookup_torrent_url_fn) - self.assertEqual('Cannot create default bittorrent URL without' - ' xenserver.torrent_base_url configuration option' - ' set.', - six.text_type(exc)) - - def test_default_fetch_url_base_url_is_set(self): - self.flags(torrent_base_url='http://foo', - group='xenserver') - - lookup_fn = self.store._lookup_torrent_url_fn() - self.assertEqual('http://foo/fakeimageid.torrent', - lookup_fn(self.image_id)) - - def test_invalid_base_url_warning_logged(self): - self.flags(torrent_base_url='www.foo.com', - group='xenserver') - - # Make sure a warning is logged when an invalid base URL is set, - # where invalid means it does not contain any slash characters - warnings = [] - - def fake_warn(msg): - warnings.append(msg) - - self.stub_out('nova.virt.xenapi.image.bittorrent.LOG.warning', - fake_warn) - - lookup_fn = self.store._lookup_torrent_url_fn() - self.assertEqual('fakeimageid.torrent', - lookup_fn(self.image_id)) - - self.assertTrue(any('does not contain a slash character' in msg for - msg in warnings), - '_lookup_torrent_url_fn() did not log a warning ' - 'message when the torrent_base_url did not contain a ' - 'slash character.') diff --git a/nova/tests/unit/virt/xenapi/test_vm_utils.py b/nova/tests/unit/virt/xenapi/test_vm_utils.py index 707931cdcb70..9a2dd46c2e74 100644 --- a/nova/tests/unit/virt/xenapi/test_vm_utils.py +++ b/nova/tests/unit/virt/xenapi/test_vm_utils.py @@ -268,33 +268,7 @@ class FetchVhdImageTestCase(VMUtilsTestBase): else: func.AndReturn({'root': {'uuid': 'vdi'}}) - def _stub_bittorrent_download_vhd(self, raise_exc=None): - self.mox.StubOutWithMock( - self.session, 'call_plugin_serialized') - func = self.session.call_plugin_serialized( - 'bittorrent.py', 'download_vhd', - image_id='image_id', - uuid_stack=["uuid_stack"], - sr_path='sr_path', - torrent_download_stall_cutoff=600, - torrent_listen_port_start=6881, - torrent_listen_port_end=6891, - torrent_max_last_accessed=86400, - torrent_max_seeder_processes_per_host=1, - torrent_seed_chance=1.0, - torrent_seed_duration=3600, - torrent_url='http://foo/image_id.torrent' - ) - if raise_exc: - func.AndRaise(raise_exc) - else: - func.AndReturn({'root': {'uuid': 'vdi'}}) - def test_fetch_vhd_image_works_with_glance(self): - self.mox.StubOutWithMock(vm_utils, '_image_uses_bittorrent') - vm_utils._image_uses_bittorrent( - self.context, self.instance).AndReturn(False) - self._stub_glance_download_vhd() self.mox.StubOutWithMock(vm_utils, 'safe_find_sr') @@ -314,37 +288,7 @@ class FetchVhdImageTestCase(VMUtilsTestBase): self.mox.VerifyAll() - def test_fetch_vhd_image_works_with_bittorrent(self): - self.flags(torrent_base_url='http://foo', group='xenserver') - - self.mox.StubOutWithMock(vm_utils, '_image_uses_bittorrent') - vm_utils._image_uses_bittorrent( - self.context, self.instance).AndReturn(True) - - self._stub_bittorrent_download_vhd() - - self.mox.StubOutWithMock(vm_utils, 'safe_find_sr') - vm_utils.safe_find_sr(self.session).AndReturn("sr") - - self.mox.StubOutWithMock(vm_utils, '_scan_sr') - vm_utils._scan_sr(self.session, "sr") - - self.mox.StubOutWithMock(vm_utils, '_check_vdi_size') - vm_utils._check_vdi_size(self.context, self.session, self.instance, - "vdi") - - self.mox.ReplayAll() - - self.assertEqual("vdi", vm_utils._fetch_vhd_image(self.context, - self.session, self.instance, 'image_id')['root']['uuid']) - - self.mox.VerifyAll() - def test_fetch_vhd_image_cleans_up_vdi_on_fail(self): - self.mox.StubOutWithMock(vm_utils, '_image_uses_bittorrent') - vm_utils._image_uses_bittorrent( - self.context, self.instance).AndReturn(False) - self._stub_glance_download_vhd() self.mox.StubOutWithMock(vm_utils, 'safe_find_sr') @@ -373,44 +317,7 @@ class FetchVhdImageTestCase(VMUtilsTestBase): self.mox.VerifyAll() - def test_fallback_to_default_handler(self): - self.flags(torrent_base_url='http://foo', group='xenserver') - - self.mox.StubOutWithMock(vm_utils, '_image_uses_bittorrent') - vm_utils._image_uses_bittorrent( - self.context, self.instance).AndReturn(True) - - self._stub_bittorrent_download_vhd(raise_exc=RuntimeError) - - vm_utils._make_uuid_stack().AndReturn(["uuid_stack"]) - vm_utils.get_sr_path(self.session).AndReturn('sr_path') - - self._stub_glance_download_vhd() - - self.mox.StubOutWithMock(vm_utils, 'safe_find_sr') - vm_utils.safe_find_sr(self.session).AndReturn("sr") - - self.mox.StubOutWithMock(vm_utils, '_scan_sr') - vm_utils._scan_sr(self.session, "sr") - - self.mox.StubOutWithMock(vm_utils, '_check_vdi_size') - vm_utils._check_vdi_size(self.context, self.session, self.instance, - "vdi") - - self.mox.ReplayAll() - - self.assertEqual("vdi", vm_utils._fetch_vhd_image(self.context, - self.session, self.instance, 'image_id')['root']['uuid']) - - self.mox.VerifyAll() - - def test_default_handler_does_not_fallback_to_itself(self): - self.flags(torrent_base_url='http://foo', group='xenserver') - - self.mox.StubOutWithMock(vm_utils, '_image_uses_bittorrent') - vm_utils._image_uses_bittorrent( - self.context, self.instance).AndReturn(False) - + def test_fetch_vhd_image_download_exception(self): self._stub_glance_download_vhd(raise_exc=RuntimeError) self.mox.ReplayAll() @@ -728,47 +635,6 @@ class CreateCachedImageTestCase(VMUtilsTestBase): vm_utils.ImageType.DISK_VHD)) -class BittorrentTestCase(VMUtilsTestBase): - def setUp(self): - super(BittorrentTestCase, self).setUp() - self.context = context.get_admin_context() - - def test_image_uses_bittorrent(self): - instance = {'system_metadata': {'image_bittorrent': True}} - self.flags(torrent_images='some', group='xenserver') - self.assertTrue(vm_utils._image_uses_bittorrent(self.context, - instance)) - - def _test_create_image(self, cache_type): - instance = {'system_metadata': {'image_cache_in_nova': True}} - self.flags(cache_images=cache_type, group='xenserver') - - was = {'called': None} - - def fake_create_cached_image(*args): - was['called'] = 'some' - return (False, {}) - self.stubs.Set(vm_utils, '_create_cached_image', - fake_create_cached_image) - - def fake_fetch_image(*args): - was['called'] = 'none' - return {} - self.stubs.Set(vm_utils, '_fetch_image', - fake_fetch_image) - - vm_utils.create_image(self.context, None, instance, - 'foo', 'bar', 'baz') - - self.assertEqual(was['called'], cache_type) - - def test_create_image_cached(self): - self._test_create_image('some') - - def test_create_image_uncached(self): - self._test_create_image('none') - - class ShutdownTestCase(VMUtilsTestBase): def test_hardshutdown_should_return_true_when_vm_is_shutdown(self): diff --git a/nova/virt/xenapi/image/bittorrent.py b/nova/virt/xenapi/image/bittorrent.py deleted file mode 100644 index 785cf78ccd29..000000000000 --- a/nova/virt/xenapi/image/bittorrent.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# 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 six.moves.urllib.parse as urlparse - -import nova.conf -from nova.i18n import _, _LW -from nova.virt.xenapi import vm_utils - -LOG = logging.getLogger(__name__) - - -CONF = nova.conf.CONF - - -class BittorrentStore(object): - @staticmethod - def _lookup_torrent_url_fn(): - """Load a "fetcher" func to get the right torrent URL. - """ - - if CONF.xenserver.torrent_base_url: - if '/' not in CONF.xenserver.torrent_base_url: - LOG.warning(_LW('Value specified in conf file for' - ' xenserver.torrent_base_url does not contain a' - ' slash character, therefore it will not be used' - ' as part of the torrent URL. Specify a valid' - ' base URL as defined by RFC 1808 (see step 6).')) - - def _default_torrent_url_fn(image_id): - return urlparse.urljoin(CONF.xenserver.torrent_base_url, - "%s.torrent" % image_id) - - return _default_torrent_url_fn - - raise RuntimeError(_('Cannot create default bittorrent URL' - ' without xenserver.torrent_base_url' - ' configuration option set.')) - - def download_image(self, context, session, instance, image_id): - params = {} - params['image_id'] = image_id - params['uuid_stack'] = vm_utils._make_uuid_stack() - params['sr_path'] = vm_utils.get_sr_path(session) - params['torrent_seed_duration'] = CONF.xenserver.torrent_seed_duration - params['torrent_seed_chance'] = CONF.xenserver.torrent_seed_chance - params['torrent_max_last_accessed'] = \ - CONF.xenserver.torrent_max_last_accessed - params['torrent_listen_port_start'] = \ - CONF.xenserver.torrent_listen_port_start - params['torrent_listen_port_end'] = \ - CONF.xenserver.torrent_listen_port_end - params['torrent_download_stall_cutoff'] = \ - CONF.xenserver.torrent_download_stall_cutoff - params['torrent_max_seeder_processes_per_host'] = \ - CONF.xenserver.torrent_max_seeder_processes_per_host - - lookup_fn = self._lookup_torrent_url_fn() - params['torrent_url'] = lookup_fn(image_id) - - vdis = session.call_plugin_serialized( - 'bittorrent.py', 'download_vhd', **params) - - return vdis - - def upload_image(self, context, session, instance, image_id, vdi_uuids): - raise NotImplementedError diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index bd70b33d8315..412f7fadda90 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -1343,42 +1343,12 @@ def _make_uuid_stack(): return [uuidutils.generate_uuid() for i in range(MAX_VDI_CHAIN_SIZE)] -def _image_uses_bittorrent(context, instance): - bittorrent = False - torrent_images = CONF.xenserver.torrent_images.lower() - - if torrent_images == 'all': - bittorrent = True - elif torrent_images == 'some': - sys_meta = utils.instance_sys_meta(instance) - try: - bittorrent = strutils.bool_from_string( - sys_meta['image_bittorrent']) - except KeyError: - pass - elif torrent_images == 'none': - pass - else: - LOG.warning(_LW("Invalid value '%s' for torrent_images"), - torrent_images) - - return bittorrent - - def _default_download_handler(): # TODO(sirp): This should be configurable like upload_handler return importutils.import_object( 'nova.virt.xenapi.image.glance.GlanceStore') -def _choose_download_handler(context, instance): - if _image_uses_bittorrent(context, instance): - return importutils.import_object( - 'nova.virt.xenapi.image.bittorrent.BittorrentStore') - else: - return _default_download_handler() - - def get_compression_level(): level = CONF.xenserver.image_compression_level if level is not None and (level < 1 or level > 9): @@ -1396,26 +1366,12 @@ def _fetch_vhd_image(context, session, instance, image_id): LOG.debug("Asking xapi to fetch vhd image %s", image_id, instance=instance) - handler = _choose_download_handler(context, instance) + handler = _default_download_handler() try: vdis = handler.download_image(context, session, instance, image_id) except Exception: - default_handler = _default_download_handler() - - # Using type() instead of isinstance() so instance of subclass doesn't - # test as equivalent - if type(handler) == type(default_handler): - raise - - LOG.exception(_LE("Download handler '%(handler)s' raised an" - " exception, falling back to default handler" - " '%(default_handler)s'"), - {'handler': handler, - 'default_handler': default_handler}) - - vdis = default_handler.download_image( - context, session, instance, image_id) + raise # Ensure we can see the import VHDs as VDIs scan_default_sr(session) diff --git a/releasenotes/notes/remove-bittorent-in-xenapi-driver-7b03447b8a1760fe.yaml b/releasenotes/notes/remove-bittorent-in-xenapi-driver-7b03447b8a1760fe.yaml new file mode 100644 index 000000000000..10c933ae6db6 --- /dev/null +++ b/releasenotes/notes/remove-bittorent-in-xenapi-driver-7b03447b8a1760fe.yaml @@ -0,0 +1,5 @@ +--- +other: + - | + With XenAPI driver, we have deprecated bittorrent since '15.0.0', so we + decide to remove all bittorrent related files and unit tests.