Remove neutronclient calls from sysinv

The code was invoking neutronclient methods such as bind, unbind
and list providernets which do not exist.

None of the neutronclient calls from within sysinv are used and
therefore all have been removed from the codebase.

This ends up removing the following methods
-    def bind_interface
-    def _get_neutronclient
-    def get_providernetworksdict
-    def iinterface_get_providernets
-    def neutron_bind_interface
-    def neutron_extension_list
-    def _neutron_host_extension_supported
-    def _neutron_providernet_extension_supported
-    def neutron_unbind_interface
-    def unbind_interface
-    def _update_shared_interface_neutron_bindings

As well as unused calls in puppet/ovs
-    def _get_neutron_config
-    def _get_providernet_type
-    def _is_vxlan_providernet

And these previously skipped tests in test_interface
-    def test_create_neutron_bind_failed
-    def test_patch_neutron_bind_failed

Change-Id: I1c81a3a7964c1581edf78b336c55e23bce4782cc
Story: 2004515
Task: 36298
Signed-off-by: Al Bailey <Al.Bailey@windriver.com>
This commit is contained in:
Al Bailey 2019-08-16 12:06:55 -05:00
parent bb8bfe81d6
commit 213ef064f9
7 changed files with 0 additions and 486 deletions

View File

@ -22,7 +22,6 @@ oslo.utils>=3.5.0 # Apache-2.0
oslo.serialization>=1.10.0,!=2.19.1 # Apache-2.0
pycrypto
python-cinderclient>=3.1.0 # Apache-2.0
python-neutronclient>=6.3.0 # Apache-2.0
python-glanceclient>=2.8.0 # Apache-2.0
python-keystoneclient>=3.8.0 # Apache-2.0
keystonemiddleware>=4.12.0 # Apache-2.0

View File

@ -52,7 +52,6 @@ from sysinv import objects
from sysinv.objects import utils as object_utils
from sysinv.openstack.common import log
from sysinv.openstack.common import uuidutils
from sysinv.openstack.common.rpc import common as rpc_common
from sysinv.openstack.common.gettextutils import _
from fm_api import constants as fm_constants
from fm_api import fm_api
@ -583,15 +582,6 @@ class InterfaceController(rest.RestController):
if _is_ipv6_address_mode_updated(interface, rpc_interface):
_update_ipv6_address_mode(interface)
# Commit operation with neutron
if (interface['ifclass'] and
interface['ifclass'] in NEUTRON_INTERFACE_CLASS):
_neutron_bind_interface(ihost, interface)
if (rpc_interface['ifclass'] and
rpc_interface['ifclass'] in NEUTRON_INTERFACE_CLASS and
interface['ifclass'] not in NEUTRON_INTERFACE_CLASS):
_neutron_unbind_interface(ihost, rpc_interface)
saved_interface = copy.deepcopy(rpc_interface)
try:
@ -618,8 +608,6 @@ class InterfaceController(rest.RestController):
for ifname in removed_members:
_update_interface_mtu(ifname, ihost, DEFAULT_MTU)
# Update shared data interface bindings, if required
_update_shared_interface_neutron_bindings(ihost, new_interface)
if sriov_update:
pecan.request.rpcapi.update_sriov_config(
pecan.request.context,
@ -630,13 +618,6 @@ class InterfaceController(rest.RestController):
LOG.exception(e)
msg = _("Interface update failed: host %s if %s : patch %s"
% (ihost['hostname'], interface['ifname'], patch))
if (saved_interface['ifclass'] and
saved_interface['ifclass'] in NEUTRON_INTERFACE_CLASS):
# Restore Neutron bindings
_neutron_bind_interface(ihost, saved_interface)
# Update shared data interface bindings, if required
_update_shared_interface_neutron_bindings(ihost, saved_interface)
raise wsme.exc.ClientSideError(msg)
@ -1442,89 +1423,6 @@ def _update_interface_mtu(ifname, host, mtu):
pecan.request.dbapi.iinterface_update(interface['uuid'], values)
def _get_shared_data_interfaces(ihost, interface):
"""
Retrieve a list of data interfaces, if any, that are dependent on
this interface (used_by) as well as the data interface(s) that
this interface depends on (uses).
"""
used_by = []
shared_data_interfaces = []
uses = interface['uses']
if uses:
for ifname in uses:
parent = pecan.request.dbapi.iinterface_get(ifname, ihost['uuid'])
used_by.extend(parent['used_by'])
interface_class = parent.get('ifclass', None)
if interface_class:
# This should only match 'data' interface class since that
# is the only type that can be shared on multiple interfaces.
if interface_class == constants.INTERFACE_CLASS_DATA:
shared_data_interfaces.append(parent)
else:
used_by = interface['used_by']
for ifname in used_by:
child = pecan.request.dbapi.iinterface_get(ifname, ihost['uuid'])
interface_class = child.get('ifclass', None)
if interface_class:
# This should only match 'data' interface class since that
# is the only type that can be shared on multiple interfaces.
if interface_class == constants.INTERFACE_CLASS_DATA:
shared_data_interfaces.append(child)
return shared_data_interfaces
def _neutron_host_extension_supported():
"""
Reports whether the neutron "host" extension is supported or not. This
indicator is used to determine whether certain neutron operations are
necessary or not. If it is not supported then this is an indication that
we are running against a vanilla openstack installation.
"""
return True
# TODO: This should be looking at the neutron extension list, but because
# our config file is not setup properly to have a different region on a per
# service basis we cannot.
#
# The code should like something like this:
#
# extensions = pecan.request.rpcapi.neutron_extension_list(
# pecan.request.context)
# return bool(constants.NEUTRON_HOST_ALIAS in extensions)
def _neutron_providernet_extension_supported():
"""
Reports whether the neutron "wrs-provider" extension is supported or not.
This indicator is used to determine whether certain neutron operations are
necessary or not. If it is not supported then this is an indication that
we are running against a vanilla openstack installation.
"""
# In the case of a kubernetes config, neutron may not be running, and
# sysinv should not rely on talking to containerized neutron.
return False
def _neutron_providernet_list():
pnets = {}
if _neutron_providernet_extension_supported():
pnets = pecan.request.rpcapi.iinterface_get_providernets(
pecan.request.context)
return pnets
def _update_shared_interface_neutron_bindings(ihost, interface, test=False):
if not _neutron_host_extension_supported():
# No action required if neutron does not support the host extension
return
shared_data_interfaces = _get_shared_data_interfaces(ihost, interface)
for shared_interface in shared_data_interfaces:
if shared_interface['uuid'] != interface['uuid']:
_neutron_bind_interface(ihost, shared_interface, test)
def _datanetworks_get_by_interface(interface_uuid):
ifdatanets = pecan.request.dbapi.interface_datanetwork_get_by_interface(
interface_uuid)
@ -1557,77 +1455,6 @@ def _datanetworks_get_by_interface(interface_uuid):
return datanetworks_names_list, datanetworks_list
def _neutron_bind_interface(ihost, interface, test=False):
"""
Send a request to neutron to bind the interface to the specified
providernetworks and perform validation against a subset of the interface
attributes.
"""
ihost_uuid = ihost['uuid']
recordtype = ihost['recordtype']
if recordtype in ['profile']:
# No action required if we are operating on a profile record
return
if not _neutron_providernet_extension_supported():
# No action required if neutron does not support the pnet extension
return
if not _neutron_host_extension_supported():
# No action required if neutron does not support the host extension
return
if interface['ifclass'] == constants.INTERFACE_CLASS_DATA:
networktype = constants.NETWORK_TYPE_DATA
elif interface['ifclass'] == constants.INTERFACE_CLASS_PCI_PASSTHROUGH:
networktype = constants.NETWORK_TYPE_PCI_PASSTHROUGH
elif interface['ifclass'] == constants.INTERFACE_CLASS_PCI_SRIOV:
networktype = constants.NETWORK_TYPE_PCI_SRIOV
else:
msg = _("Invalid interface class %s: " % interface['ifclass'])
raise wsme.exc.ClientSideError(msg)
interface_uuid = interface['uuid']
datanetworks_names_list, _dl = \
_datanetworks_get_by_interface(interface_uuid)
providernetworks = ",".join([str(x) for x in datanetworks_names_list])
LOG.info("_neutron_bind_interface uuid=%s datanetworks_names=%s" %
(interface_uuid, providernetworks))
vlans = _get_interface_vlans(ihost_uuid, interface)
try:
# Send the request to neutron
pecan.request.rpcapi.neutron_bind_interface(
pecan.request.context,
ihost_uuid, interface_uuid, networktype, providernetworks,
interface['imtu'], vlans=vlans, test=test)
except rpc_common.RemoteError as e:
raise wsme.exc.ClientSideError(str(e.value))
def _neutron_unbind_interface(ihost, interface):
"""
Send a request to neutron to unbind the interface from all provider
networks.
"""
ihost_uuid = ihost['uuid']
recordtype = ihost['recordtype']
if recordtype in ['profile']:
# No action required if we are operating on a profile record
return
if not _neutron_providernet_extension_supported():
# No action required if neutron does not support the pnet extension
return
if not _neutron_host_extension_supported():
# No action required if neutron does not support the host extension
return
try:
# Send the request to neutron
pecan.request.rpcapi.neutron_unbind_interface(
pecan.request.context, ihost_uuid, interface['uuid'])
except rpc_common.RemoteError as e:
raise wsme.exc.ClientSideError(str(e.value))
def _get_boot_interface(ihost):
"""
Find the interface from which this host booted.
@ -1783,28 +1610,6 @@ def _create(interface, from_profile=False):
pecan.request.dbapi.iinterface_destroy(new_interface.as_dict()['uuid'])
raise e
try:
if (interface['ifclass'] and
interface['ifclass'] in NEUTRON_INTERFACE_CLASS):
_neutron_bind_interface(ihost, new_interface.as_dict())
except Exception as e:
LOG.exception("Failed to update neutron bindings: "
"new_interface={} interface={}".format(
new_interface.as_dict(), interface))
pecan.request.dbapi.iinterface_destroy(new_interface.as_dict()['uuid'])
raise e
try:
_update_shared_interface_neutron_bindings(ihost, new_interface.as_dict())
except Exception as e:
LOG.exception("Failed to update neutron bindings for shared "
"interfaces: new_interface={} interface={}".format(
new_interface.as_dict(), interface))
pecan.request.dbapi.iinterface_destroy(interface['uuid'])
_neutron_unbind_interface(ihost, new_interface.as_dict())
_update_shared_interface_neutron_bindings(ihost, new_interface.as_dict())
raise e
# Update ports
if ports:
try:
@ -1813,9 +1618,6 @@ def _create(interface, from_profile=False):
LOG.exception("Failed to update ports for interface "
"interfaces: new_interface={} ports={}".format(
new_interface.as_dict(), ports))
if (interface['ifclass'] and
interface['ifclass'] in NEUTRON_INTERFACE_CLASS):
_neutron_unbind_interface(ihost, new_interface.as_dict())
pecan.request.dbapi.iinterface_destroy(new_interface.as_dict()['uuid'])
raise e
@ -1996,12 +1798,6 @@ def _delete(interface, from_profile=False):
interface['id']
)
pecan.request.dbapi.iinterface_destroy(interface['uuid'])
if (interface['ifclass'] and
interface['ifclass'] in NEUTRON_INTERFACE_CLASS):
# Unbind the interface in neutron
_neutron_unbind_interface(ihost, interface)
# Update shared data interface bindings, if required
_update_shared_interface_neutron_bindings(ihost, interface)
# Clear outstanding alarms that were raised by the neutron vswitch
# agent against interface
_clear_interface_state_fault(ihost['hostname'], interface['uuid'])

View File

@ -8097,17 +8097,6 @@ class ConductorManager(service.PeriodicService):
pv_dict = {'disk_or_part_device_path': idisk.device_path}
self.dbapi.ipv_update(ipv['uuid'], pv_dict)
def iinterface_get_providernets(self, context, pn_names=None):
"""
Gets names and MTUs for providernets in neutron
If param 'pn_names' is provided, returns dict for
only specified providernets, else: returns all
providernets in neutron
"""
return self._openstack.get_providernetworksdict(pn_names)
def iinterfaces_get_by_ihost_nettype(self,
context,
ihost_uuid,
@ -8189,35 +8178,6 @@ class ConductorManager(service.PeriodicService):
interface_id)
return address
def neutron_extension_list(self, context):
"""
Send a request to neutron to query the supported extension list.
"""
response = self._openstack.neutron_extension_list(context)
return response
def neutron_bind_interface(self, context, host_uuid, interface_uuid,
network_type, providernets, mtu,
vlans=None, test=False):
"""
Send a request to neutron to bind an interface to a set of provider
networks, and inform neutron of some key attributes of the interface
for semantic checking purposes.
"""
response = self._openstack.bind_interface(
context, host_uuid, interface_uuid, network_type,
providernets, mtu, vlans=vlans, test=test)
return response
def neutron_unbind_interface(self, context, host_uuid, interface_uuid):
"""
Send a request to neutron to unbind an interface from a set of
provider networks.
"""
response = self._openstack.unbind_interface(
context, host_uuid, interface_uuid)
return response
def vim_host_add(self, context, api_token, ihost_uuid,
hostname, subfunctions, administrative,
operational, availability,

View File

@ -19,7 +19,6 @@ from sysinv.common.storage_backend_conf import StorageBackendConfig
from sysinv.openstack.common.gettextutils import _
from sysinv.openstack.common import log as logging
from novaclient.v2 import client as nova_client_v2
from neutronclient.v2_0 import client as neutron_client_v2_0
from oslo_config import cfg
from keystoneclient.v3 import client as keystone_client
from keystoneclient.auth.identity import v3
@ -136,8 +135,6 @@ class OpenStackOperator(object):
self.openstack_keystone_client = None
self.openstack_keystone_session = None
self.nova_client = None
self.neutron_client = None
self._neutron_extension_list = []
self._auth_url = cfg.CONF[PLATFORM_CONFIG].auth_url + "/v3"
self._openstack_auth_url = cfg.CONF[OPENSTACK_CONFIG].auth_url + "/v3"
@ -152,92 +149,6 @@ class OpenStackOperator(object):
raise exception.InvalidParameterValue(
_("Unrecognized keystone service_config."))
#################
# NEUTRON
#################
def _get_neutronclient(self):
if not self.neutron_client: # should not cache this forever
# neutronclient doesn't yet support v3 keystone auth
# use keystoneauth.session
self.neutron_client = neutron_client_v2_0.Client(
session=self._get_keystone_session(OPENSTACK_CONFIG),
auth_url=self._get_auth_url(OPENSTACK_CONFIG),
endpoint_type='internalURL',
region_name=cfg.CONF[OPENSTACK_CONFIG].neutron_region_name)
return self.neutron_client
def get_providernetworksdict(self, pn_names=None, quiet=False):
"""
Returns names and MTU values of neutron's providernetworks
"""
pn_dict = {}
# Call neutron
try:
pn_list = self._get_neutronclient().list_providernets().get('providernets', [])
except Exception as e:
if not quiet:
LOG.error("Failed to access Neutron client")
LOG.error(e)
return pn_dict
# Get dict
# If no names specified, will add all providenets to dict
for pn in pn_list:
if pn_names and pn['name'] not in pn_names:
continue
else:
pn_dict.update({pn['name']: pn})
return pn_dict
def neutron_extension_list(self, context):
"""
Send a request to neutron to query the supported extension list.
"""
if not self._neutron_extension_list:
client = self._get_neutronclient()
extensions = client.list_extensions().get('extensions', [])
self._neutron_extension_list = [e['alias'] for e in extensions]
return self._neutron_extension_list
def bind_interface(self, context, host_uuid, interface_uuid,
network_type, providernets, mtu,
vlans=None, test=False):
"""
Send a request to neutron to bind an interface to a set of provider
networks, and inform neutron of some key attributes of the interface
for semantic checking purposes.
Any remote exceptions from neutron are allowed to pass-through and are
expected to be handled by the caller.
"""
client = self._get_neutronclient()
body = {'interface': {'uuid': interface_uuid,
'providernets': providernets,
'network_type': network_type,
'mtu': mtu}}
if vlans:
body['interface']['vlans'] = vlans
if test:
body['interface']['test'] = True
client.host_bind_interface(host_uuid, body=body)
return True
def unbind_interface(self, context, host_uuid, interface_uuid):
"""
Send a request to neutron to unbind an interface from a set of
provider networks.
Any remote exceptions from neutron are allowed to pass-through and are
expected to be handled by the caller.
"""
client = self._get_neutronclient()
body = {'interface': {'uuid': interface_uuid}}
client.host_unbind_interface(host_uuid, body=body)
return True
#################
# NOVA
#################

View File

@ -1041,24 +1041,6 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
host_uuid=host_uuid,
))
def iinterface_get_providernets(self,
context,
pn_names=None):
"""Call neutron to get PN MTUs based on PN names
This method does not update any records in the db
:param context: an admin context
:param pn_names: a list of providenet names
:returns: pass or fail
"""
pn_dict = self.call(context,
self.make_msg('iinterface_get_providernets',
pn_names=pn_names))
return pn_dict
def mgmt_ip_set_by_ihost(self,
context,
ihost_uuid,
@ -1080,40 +1062,6 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
interface_id=interface_id,
mgmt_ip=mgmt_ip))
def neutron_extension_list(self, context):
"""
Send a request to neutron to query the supported extension list.
"""
return self.call(context, self.make_msg('neutron_extension_list'))
def neutron_bind_interface(self, context, host_uuid, interface_uuid,
network_type, providernets, mtu,
vlans=None, test=False):
"""
Send a request to neutron to bind an interface to a set of provider
networks, and inform neutron of some key attributes of the interface
for semantic checking purposes.
"""
return self.call(context,
self.make_msg('neutron_bind_interface',
host_uuid=host_uuid,
interface_uuid=interface_uuid,
network_type=network_type,
providernets=providernets,
mtu=mtu,
vlans=vlans,
test=test))
def neutron_unbind_interface(self, context, host_uuid, interface_uuid):
"""
Send a request to neutron to unbind an interface from a set of
provider networks.
"""
return self.call(context,
self.make_msg('neutron_unbind_interface',
host_uuid=host_uuid,
interface_uuid=interface_uuid))
def vim_host_add(self, context, api_token, ihost_uuid,
hostname, subfunctions, administrative,
operational, availability,

View File

@ -28,7 +28,6 @@ class OVSPuppet(base.BasePuppet):
config.update(self._get_memory_config(host))
config.update(self._get_port_config(host))
config.update(self._get_virtual_config(host))
config.update(self._get_neutron_config(host))
config.update(self._get_lldp_config(host))
return config
@ -378,47 +377,6 @@ class OVSPuppet(base.BasePuppet):
def _is_vxlan_datanet(self, datanet):
return datanet.get('network_type') == constants.DATANETWORK_TYPE_VXLAN
def _get_neutron_config(self, host):
local_ip = None
tunnel_types = set()
bridge_mappings = []
for iface in self.context['interfaces'].values():
if interface.is_data_network_type(iface):
# obtain the assigned bridge for interface
brname = iface.get('_ovs_bridge')
if brname:
datanets = interface.get_interface_datanets(
self.context, iface)
for datanet in datanets:
if self._is_vxlan_datanet(datanet):
address = \
interface.get_interface_primary_address(
self.context, iface)
if address:
local_ip = address['address']
tunnel_types.add(
constants.DATANETWORK_TYPE_VXLAN)
else:
bridge_mappings.append('%s:%s' %
(datanet['name'], brname))
neutron_dict = {
'neutron::agents::ml2::ovs::local_ip': local_ip,
'neutron::agents::ml2::ovs::tunnel_types': list(tunnel_types),
'neutron::agents::ml2::ovs::bridge_mappings': bridge_mappings
}
LOG.debug("OVS get_neutron_config neutron_dict=%s" % neutron_dict)
return neutron_dict
def _get_providernet_type(self, name):
if name in self.context['providernets']:
return self.context['providernets'][name]['type']
def _is_vxlan_providernet(self, name):
providernet_type = self._get_providernet_type(name)
return bool(providernet_type == constants.NEUTRON_PROVIDERNET_VXLAN)
def _get_lldp_config(self, host):
driver_list = self.context['_lldp_drivers']
driver_list.append('ovs')

View File

@ -12,17 +12,13 @@ Tests for the API /interfaces/ methods.
"""
import mock
import testtools
from six.moves import http_client
from sysinv.api.controllers.v1 import interface as api_if_v1
from sysinv.common import constants
from sysinv.conductor import rpcapi
from sysinv.tests.api import base
from sysinv.tests.db import utils as dbutils
from sysinv.db import api as db_api
from sysinv.db.sqlalchemy import api as dbsql_api
from sysinv.openstack.common.rpc import common as rpc_common
providernet_list = {
@ -153,13 +149,6 @@ class InterfaceTestCase(base.FunctionalTest):
self.mock_lower_macs.return_value = {'enp0s18': '08:00:27:8a:87:48',
'enp0s19': '08:00:27:ea:93:8e'}
self.addCleanup(p.stop)
p = mock.patch.object(rpcapi.ConductorAPI,
'iinterface_get_providernets')
self.mock_iinterface_get_providernets = p.start()
self.mock_iinterface_get_providernets.return_value = providernet_list
self.addCleanup(p.stop)
self._setup_context()
def _get_path(self, path=None):
@ -1706,32 +1695,6 @@ class TestCpePost(InterfaceTestCase):
self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message'])
@testtools.skip("deprecate neutron bind interface")
@mock.patch.object(dbsql_api.Connection, 'iinterface_destroy')
@mock.patch.object(rpcapi.ConductorAPI, 'neutron_bind_interface')
def test_create_neutron_bind_failed(self, mock_neutron_bind_interface,
mock_iinterface_destroy):
self._create_ethernet('enp0s9', constants.NETWORK_TYPE_NONE)
mock_neutron_bind_interface.side_effect = [
None,
rpc_common.RemoteError(
mock.Mock(status=404), 'not found')
]
ndict = dbutils.post_get_test_interface(
forihostid=self.controller.id,
ihost_uuid=self.controller.uuid,
datanetworks='group0-ext1',
ifname='data1',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype=constants.INTERFACE_TYPE_ETHERNET,
uses=['enp0s9'])
self._post_and_check_failure(ndict)
mock_neutron_bind_interface.assert_called_with(
mock.ANY, mock.ANY, mock.ANY, constants.NETWORK_TYPE_DATA,
mock.ANY, mock.ANY, vlans=mock.ANY, test=mock.ANY)
mock_iinterface_destroy.assert_called_once_with(mock.ANY)
# Expected error: Data interface data0 is already attached to this
# Data Network: group0-data0.
def test_create_invalid_data_network_used(self):
@ -1808,27 +1771,6 @@ class TestCpePatch(InterfaceTestCase):
admin=constants.ADMIN_LOCKED)
self._create_datanetworks()
@testtools.skip("deprecate neutron bind interface")
@mock.patch.object(rpcapi.ConductorAPI, 'neutron_bind_interface')
def test_patch_neutron_bind_failed(self, mock_neutron_bind_interface):
port, interface = self._create_ethernet(
'data0', networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
datanetworks='group0-data0')
mock_neutron_bind_interface.side_effect = [
None,
rpc_common.RemoteError(
mock.Mock(return_value={'status': 404}), 'not found'),
None]
patch_result = self.patch_dict_json(
'%s' % self._get_path(interface['uuid']),
imtu=2000, expect_errors=True)
self.assertEqual(http_client.BAD_REQUEST, patch_result.status_int)
self.assertEqual('application/json', patch_result.content_type)
self.assertTrue(patch_result.json['error_message'])
# Expected error: Value for number of SR-IOV VFs must be > 0.
def test_invalid_sriov_numvfs(self):
port, interface = self._create_ethernet('eth0',