From a6dbf97242caa3be646e8eb6b1502b5e59e123fd Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Tue, 17 Nov 2020 14:33:50 +0000 Subject: [PATCH] Deprecate XenAPI support The configuration options are now marked as deprecated for removal in X release. Any related code is deleted. Neutron does not support XenAPI, same as Nova [1][2]. [1]https://review.opendev.org/#/c/749304/ [2]https://review.opendev.org/#/c/749309/ Change-Id: Ifdb2200a5dac3508fdf8907bdd1f4547dff35341 Story: #2007686 Task: #41269 --- .../openvswitch_agent.ini | 1 - lower-constraints.txt | 1 - neutron/agent/linux/utils.py | 9 +- neutron/agent/linux/xenapi_root_helper.py | 92 ------------------- neutron/conf/agent/common.py | 4 - neutron/conf/agent/xenapi_conf.py | 22 +++-- neutron/opts.py | 8 -- .../openvswitch/agent/ovs_neutron_agent.py | 15 --- neutron/tests/unit/agent/linux/test_utils.py | 10 -- .../agent/linux/test_xenapi_root_helper.py | 86 ----------------- ...emove_xenapi_support-2cc2a4b9ad0ef01d.yaml | 7 ++ requirements.txt | 1 - 12 files changed, 23 insertions(+), 233 deletions(-) delete mode 100644 neutron/agent/linux/xenapi_root_helper.py delete mode 100644 neutron/tests/unit/agent/linux/test_xenapi_root_helper.py create mode 100644 releasenotes/notes/remove_xenapi_support-2cc2a4b9ad0ef01d.yaml diff --git a/etc/oslo-config-generator/openvswitch_agent.ini b/etc/oslo-config-generator/openvswitch_agent.ini index 79478d39957..3fab70d3921 100644 --- a/etc/oslo-config-generator/openvswitch_agent.ini +++ b/etc/oslo-config-generator/openvswitch_agent.ini @@ -3,5 +3,4 @@ output_file = etc/neutron/plugins/ml2/openvswitch_agent.ini.sample wrap_width = 79 namespace = neutron.ml2.ovs.agent -namespace = neutron.ml2.xenapi namespace = oslo.log diff --git a/lower-constraints.txt b/lower-constraints.txt index 2c22c6c5754..a0dada5f670 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -58,7 +58,6 @@ os-client-config==1.28.0 os-ken==0.3.0 os-service-types==1.7.0 os-vif==1.15.1 -os-xenapi==0.3.4 osc-lib==1.8.0 oslo.cache==1.26.0 oslo.concurrency==3.26.0 diff --git a/neutron/agent/linux/utils.py b/neutron/agent/linux/utils.py index 73ad326bfe2..f2221a3cccb 100644 --- a/neutron/agent/linux/utils.py +++ b/neutron/agent/linux/utils.py @@ -36,7 +36,6 @@ from oslo_utils import fileutils import psutil from neutron._i18n import _ -from neutron.agent.linux import xenapi_root_helper from neutron.common import utils from neutron.conf.agent import common as config from neutron import wsgi @@ -57,12 +56,8 @@ class RootwrapDaemonHelper(object): def get_client(cls): with cls.__lock: if cls.__client is None: - if (xenapi_root_helper.ROOT_HELPER_DAEMON_TOKEN == - cfg.CONF.AGENT.root_helper_daemon): - cls.__client = xenapi_root_helper.XenAPIClient() - else: - cls.__client = client.Client( - shlex.split(cfg.CONF.AGENT.root_helper_daemon)) + cls.__client = client.Client( + shlex.split(cfg.CONF.AGENT.root_helper_daemon)) return cls.__client diff --git a/neutron/agent/linux/xenapi_root_helper.py b/neutron/agent/linux/xenapi_root_helper.py deleted file mode 100644 index 9274dc7e493..00000000000 --- a/neutron/agent/linux/xenapi_root_helper.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (c) 2016 Citrix System. -# 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. - -"""xenapi root helper - -For xenapi, we may need to run some commands in dom0 with additional privilege. -This xenapi root helper contains the class of XenAPIClient to support it: -XenAPIClient will keep a XenAPI session to dom0 and allow to run commands -in dom0 via calling XenAPI plugin. The XenAPI plugin is responsible to -determine whether a command is safe to execute. -""" - -from os_xenapi.client import session -from os_xenapi.client import XenAPI -from oslo_config import cfg -from oslo_log import log as logging -from oslo_rootwrap import cmd as oslo_rootwrap_cmd -from oslo_serialization import jsonutils - -from neutron.conf.agent import xenapi_conf - - -ROOT_HELPER_DAEMON_TOKEN = 'xenapi_root_helper' # nosec - -RC_UNKNOWN_XENAPI_ERROR = 80 -MSG_UNAUTHORIZED = "Unauthorized command" -MSG_NOT_FOUND = "Executable not found" -XENAPI_PLUGIN_FAILURE_ID = "XENAPI_PLUGIN_FAILURE" - -LOG = logging.getLogger(__name__) -xenapi_conf.register_xenapi_opts(cfg.CONF) - - -class XenAPIClient(object): - def __init__(self): - self._session = self._create_session( - cfg.CONF.xenapi.connection_url, - cfg.CONF.xenapi.connection_username, - cfg.CONF.xenapi.connection_password) - - def _call_plugin(self, plugin, fn, args): - return self._session.call_plugin(plugin, fn, args) - - def _create_session(self, url, username, password): - return session.XenAPISession(url, username, password, - originator="neutron") - - def _get_return_code(self, failure_details): - # The details will be as: - # [XENAPI_PLUGIN_FAILURE_ID, methodname, except_class_name, message] - # We can distinguish the error type by checking the message string. - if (len(failure_details) == 4 and - XENAPI_PLUGIN_FAILURE_ID == failure_details[0]): - if (MSG_UNAUTHORIZED == failure_details[3]): - return oslo_rootwrap_cmd.RC_UNAUTHORIZED - elif (MSG_NOT_FOUND == failure_details[3]): - return oslo_rootwrap_cmd.RC_NOEXECFOUND - # otherwise we get unexpected exception. - return RC_UNKNOWN_XENAPI_ERROR - - def execute(self, cmd, stdin=None): - out = "" - err = "" - if cmd is None or len(cmd) == 0: - err = "No command specified." - return oslo_rootwrap_cmd.RC_NOCOMMAND, out, err - try: - result_raw = self._call_plugin( - 'netwrap.py', 'run_command', - {'cmd': jsonutils.dumps(cmd), - 'cmd_input': jsonutils.dumps(stdin)}) - result = jsonutils.loads(result_raw) - returncode = result['returncode'] - out = result['out'] - err = result['err'] - return returncode, out, err - except XenAPI.Failure as failure: - LOG.exception('Failed to execute command: %s', cmd) - returncode = self._get_return_code(failure.details) - return returncode, out, err diff --git a/neutron/conf/agent/common.py b/neutron/conf/agent/common.py index 9cc12a8b453..ba021879a8a 100644 --- a/neutron/conf/agent/common.py +++ b/neutron/conf/agent/common.py @@ -105,10 +105,6 @@ in "daemon mode" which has been reported to improve performance at scale. For more information on running rootwrap in "daemon mode", see: https://docs.openstack.org/oslo.rootwrap/latest/user/usage.html#daemon-mode - -For the agent which needs to execute commands in Dom0 in the hypervisor of -XenServer, this option should be set to 'xenapi_root_helper', so that it will -keep a XenAPI session to pass commands to Dom0. """)), ] diff --git a/neutron/conf/agent/xenapi_conf.py b/neutron/conf/agent/xenapi_conf.py index ce9d095a7fa..a77a5416b6b 100644 --- a/neutron/conf/agent/xenapi_conf.py +++ b/neutron/conf/agent/xenapi_conf.py @@ -17,20 +17,26 @@ from oslo_config import cfg from neutron._i18n import _ -XENAPI_CONF_SECTION = 'xenapi' +XENAPI_DEPRECATION_REASON = ('XenAPI support has been removed from Nova, it ' + 'will be removed in X.') XENAPI_OPTS = [ cfg.StrOpt('connection_url', - help=_("URL for connection to XenServer/Xen Cloud Platform.")), + help=_("URL for connection to XenServer/Xen Cloud Platform."), + deprecated_for_removal=True, + deprecated_since='Wallaby', + deprecated_reason=XENAPI_DEPRECATION_REASON), cfg.StrOpt('connection_username', help=_("Username for connection to XenServer/Xen Cloud " - "Platform.")), + "Platform."), + deprecated_for_removal=True, + deprecated_since='Wallaby', + deprecated_reason=XENAPI_DEPRECATION_REASON), cfg.StrOpt('connection_password', help=_("Password for connection to XenServer/Xen Cloud " "Platform."), - secret=True) + secret=True, + deprecated_for_removal=True, + deprecated_since='Wallaby', + deprecated_reason=XENAPI_DEPRECATION_REASON) ] - - -def register_xenapi_opts(cfg=cfg.CONF): - cfg.register_opts(XENAPI_OPTS, group=XENAPI_CONF_SECTION) diff --git a/neutron/opts.py b/neutron/opts.py index 7b044096b70..97df2f2ee45 100644 --- a/neutron/opts.py +++ b/neutron/opts.py @@ -31,7 +31,6 @@ import neutron.conf.agent.linux import neutron.conf.agent.metadata.config as meta_conf import neutron.conf.agent.ovs_conf import neutron.conf.agent.ovsdb_api -import neutron.conf.agent.xenapi_conf import neutron.conf.common import neutron.conf.db.dvr_mac_db import neutron.conf.db.extraroute_db @@ -341,10 +340,3 @@ def list_ironic_auth_opts(): opt_list.append(plugin_option) opt_list.sort(key=operator.attrgetter('name')) return [(IRONIC_GROUP, opt_list)] - - -def list_xenapi_opts(): - return [ - ('xenapi', - neutron.conf.agent.xenapi_conf.XENAPI_OPTS) - ] diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index 874f9d57f45..b3dc1aacf2f 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -53,7 +53,6 @@ from neutron.agent.common import ovs_lib from neutron.agent.common import polling from neutron.agent.common import utils from neutron.agent.l2 import l2_agent_extensions_manager as ext_manager -from neutron.agent.linux import xenapi_root_helper from neutron.agent import rpc as agent_rpc from neutron.agent import securitygroups_rpc as agent_sg_rpc from neutron.api.rpc.callbacks import resources @@ -62,7 +61,6 @@ from neutron.api.rpc.handlers import securitygroups_rpc as sg_rpc from neutron.common import config from neutron.common import utils as n_utils from neutron.conf.agent import common as agent_config -from neutron.conf.agent import xenapi_conf from neutron.conf import service as service_conf from neutron.plugins.ml2.drivers.agent import capabilities from neutron.plugins.ml2.drivers.l2pop.rpc_manager import l2population_rpc @@ -2769,20 +2767,7 @@ def validate_tunnel_config(tunnel_types, local_ip): raise SystemExit(1) -def prepare_xen_compute(): - is_xen_compute_host = 'rootwrap-xen-dom0' in cfg.CONF.AGENT.root_helper \ - or xenapi_root_helper.ROOT_HELPER_DAEMON_TOKEN == \ - cfg.CONF.AGENT.root_helper_daemon - if is_xen_compute_host: - xenapi_conf.register_xenapi_opts() - # Force ip_lib to always use the root helper to ensure that ip - # commands target xen dom0 rather than domU. - cfg.CONF.register_opts(ip_lib.OPTS) - cfg.CONF.set_default('ip_lib_force_root', True) - - def main(bridge_classes): - prepare_xen_compute() ovs_capabilities.register() ext_manager.register_opts(cfg.CONF) agent_config.setup_privsep() diff --git a/neutron/tests/unit/agent/linux/test_utils.py b/neutron/tests/unit/agent/linux/test_utils.py index 308c7f0adad..68938726f71 100644 --- a/neutron/tests/unit/agent/linux/test_utils.py +++ b/neutron/tests/unit/agent/linux/test_utils.py @@ -40,16 +40,6 @@ class AgentUtilsExecuteTest(base.BaseTestCase): self.process.return_value.returncode = 0 self.mock_popen = self.process.return_value.communicate - def test_xenapi_root_helper(self): - token = utils.xenapi_root_helper.ROOT_HELPER_DAEMON_TOKEN - self.config(group='AGENT', root_helper_daemon=token) - with mock.patch( - 'neutron.agent.linux.utils.xenapi_root_helper.XenAPIClient')\ - as mock_xenapi_class: - mock_client = mock_xenapi_class.return_value - cmd_client = utils.RootwrapDaemonHelper.get_client() - self.assertEqual(cmd_client, mock_client) - def test_without_helper(self): expected = "%s\n" % self.test_file self.mock_popen.return_value = [expected, ""] diff --git a/neutron/tests/unit/agent/linux/test_xenapi_root_helper.py b/neutron/tests/unit/agent/linux/test_xenapi_root_helper.py deleted file mode 100644 index 6fff5d59828..00000000000 --- a/neutron/tests/unit/agent/linux/test_xenapi_root_helper.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2016 Citrix System. -# -# 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 unittest import mock - -from oslo_config import cfg -from oslo_rootwrap import cmd as oslo_rootwrap_cmd - -from neutron.agent.linux import xenapi_root_helper as helper -from neutron.conf.agent import xenapi_conf -from neutron.tests import base - - -class TestXenapiRootHelper(base.BaseTestCase): - def _get_fake_xenapi_client(self): - class FakeXenapiClient(helper.XenAPIClient): - def __init__(self): - self._session = mock.MagicMock() - - return FakeXenapiClient() - - def setUp(self): - super(TestXenapiRootHelper, self).setUp() - conf = cfg.CONF - xenapi_conf.register_xenapi_opts(conf) - - def test_get_return_code_unauthourized(self): - failure_details = [helper.XENAPI_PLUGIN_FAILURE_ID, - 'run_command', - 'PluginError', - helper.MSG_UNAUTHORIZED] - xenapi_client = self._get_fake_xenapi_client() - rc = xenapi_client._get_return_code(failure_details) - self.assertEqual(oslo_rootwrap_cmd.RC_UNAUTHORIZED, rc) - - def test_get_return_code_noexecfound(self): - failure_details = [helper.XENAPI_PLUGIN_FAILURE_ID, - 'run_command', - 'PluginError', - helper.MSG_NOT_FOUND] - xenapi_client = self._get_fake_xenapi_client() - rc = xenapi_client._get_return_code(failure_details) - self.assertEqual(oslo_rootwrap_cmd.RC_NOEXECFOUND, rc) - - def test_get_return_code_unknown_error(self): - failure_details = [helper.XENAPI_PLUGIN_FAILURE_ID, - 'run_command', - 'PluginError', - 'Any unknown error'] - xenapi_client = self._get_fake_xenapi_client() - rc = xenapi_client._get_return_code(failure_details) - self.assertEqual(helper.RC_UNKNOWN_XENAPI_ERROR, rc) - - def test_execute(self): - cmd = ["ovs-vsctl", "list-ports", "xapi2"] - expect_cmd_args = {'cmd': '["ovs-vsctl", "list-ports", "xapi2"]', - 'cmd_input': 'null'} - raw_result = '{"returncode": 0, "err": "", "out": "vif158.2"}' - - with mock.patch.object(helper.XenAPIClient, "_call_plugin", - return_value=raw_result) as mock_call_plugin: - xenapi_client = self._get_fake_xenapi_client() - rc, out, err = xenapi_client.execute(cmd) - - mock_call_plugin.assert_called_once_with( - 'netwrap.py', 'run_command', expect_cmd_args) - self.assertEqual(0, rc) - self.assertEqual("vif158.2", out) - self.assertEqual("", err) - - def test_execute_nocommand(self): - cmd = [] - xenapi_client = self._get_fake_xenapi_client() - rc, out, err = xenapi_client.execute(cmd) - self.assertEqual(oslo_rootwrap_cmd.RC_NOCOMMAND, rc) diff --git a/releasenotes/notes/remove_xenapi_support-2cc2a4b9ad0ef01d.yaml b/releasenotes/notes/remove_xenapi_support-2cc2a4b9ad0ef01d.yaml new file mode 100644 index 00000000000..29b480b3543 --- /dev/null +++ b/releasenotes/notes/remove_xenapi_support-2cc2a4b9ad0ef01d.yaml @@ -0,0 +1,7 @@ +--- +deprecations: + - | + Removed ``XenAPI`` support in Neutron. This driver is no longer supported + in Nova and Neutron. + The configuration options have been marked as "deprecated for removal" and + will be removed in X release. diff --git a/requirements.txt b/requirements.txt index df01105a133..5a1cb5b1e86 100644 --- a/requirements.txt +++ b/requirements.txt @@ -54,7 +54,6 @@ pyOpenSSL>=17.1.0 # Apache-2.0 python-novaclient>=9.1.0 # Apache-2.0 openstacksdk>=0.31.2 # Apache-2.0 python-designateclient>=2.7.0 # Apache-2.0 -os-xenapi>=0.3.4 # Apache-2.0 os-vif>=1.15.1 # Apache-2.0 futurist>=1.2.0 # Apache-2.0 tooz>=1.58.0 # Apache-2.0