Update neutron_vif driver to use OpenStackSDK.

Implements: blueprint switch-to-openstacksdk
Change-Id: I3c09906b005be429907a539bc8f5fd5047028147
This commit is contained in:
Roman Dobosz 2019-11-29 15:21:53 +01:00
parent e54ff6221c
commit a4bc6e8c3a
5 changed files with 76 additions and 114 deletions

View File

@ -13,9 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from keystoneauth1 import exceptions as key_exc
from kuryr.lib import constants as kl_const
from neutronclient.common import exceptions as n_exc
from openstack import exceptions as os_exc
from oslo_log import log as logging
from kuryr_kubernetes import clients
@ -34,39 +33,38 @@ class NeutronPodVIFDriver(base.PodVIFDriver):
"""Manages normal Neutron ports to provide VIFs for Kubernetes Pods."""
def request_vif(self, pod, project_id, subnets, security_groups):
neutron = clients.get_neutron_client()
os_net = clients.get_network_client()
rq = self._get_port_request(pod, project_id, subnets, security_groups)
port = neutron.create_port(rq).get('port')
utils.tag_neutron_resources('ports', [port['id']])
vif_plugin = self._get_vif_plugin(port)
port = os_net.create_port(**rq)
utils.tag_neutron_resources('ports', [port.id])
return ovu.neutron_to_osvif_vif(vif_plugin, port, subnets)
return ovu.neutron_to_osvif_vif(port.binding_vif_type, port, subnets)
def request_vifs(self, pod, project_id, subnets, security_groups,
num_ports):
neutron = clients.get_neutron_client()
os_net = clients.get_network_client()
rq = self._get_port_request(pod, project_id, subnets, security_groups,
unbound=True)
bulk_port_rq = {'ports': [rq] * num_ports}
try:
ports = neutron.create_port(bulk_port_rq).get('ports')
except n_exc.NeutronClientException:
ports = list(os_net.create_ports(bulk_port_rq))
except os_exc.SDKException:
LOG.exception("Error creating bulk ports: %s", bulk_port_rq)
raise
utils.tag_neutron_resources('ports', [port['id'] for port in ports])
utils.tag_neutron_resources('ports', [port.id for port in ports])
vif_plugin = self._get_vif_plugin(ports[0])
vif_plugin = ports[0].binding_vif_type
# NOTE(ltomasbo): Due to the bug (1696051) on neutron bulk port
# creation request returning the port objects without binding
# information, an additional port show is performed to get the binding
# information
if vif_plugin == 'unbound':
port_info = neutron.show_port(ports[0]['id']).get('port')
vif_plugin = self._get_vif_plugin(port_info)
port_info = os_net.get_port(ports[0].id)
vif_plugin = port_info.binding_vif_type
vifs = []
for port in ports:
@ -75,22 +73,16 @@ class NeutronPodVIFDriver(base.PodVIFDriver):
return vifs
def release_vif(self, pod, vif, project_id=None, security_groups=None):
neutron = clients.get_neutron_client()
try:
neutron.delete_port(vif.id)
except n_exc.PortNotFoundClient:
LOG.debug('Unable to release port %s as it no longer exists.',
vif.id)
clients.get_network_client().delete_port(vif.id)
def activate_vif(self, pod, vif):
if vif.active:
return
neutron = clients.get_neutron_client()
os_net = clients.get_network_client()
try:
port = neutron.show_port(vif.id).get('port')
except (key_exc.ConnectionError, n_exc.ConnectionFailed):
port = os_net.get_port(vif.id)
except os_exc.SDKException:
LOG.debug("Unable to obtain port information, retrying.")
raise k_exc.ResourceNotReady(vif)
@ -100,18 +92,12 @@ class NeutronPodVIFDriver(base.PodVIFDriver):
vif.active = True
def update_vif_sgs(self, pod, security_groups):
neutron = clients.get_neutron_client()
os_net = clients.get_network_client()
pod_state = utils.get_pod_state(pod)
if pod_state:
# NOTE(ltomasbo): It just updates the default_vif security group
port_id = pod_state.vifs[constants.DEFAULT_IFNAME].id
neutron.update_port(port_id,
{
"port": {
'security_groups': list(
security_groups)
}
})
os_net.update_port(port_id, security_groups=list(security_groups))
def _get_port_request(self, pod, project_id, subnets, security_groups,
unbound=False):
@ -120,7 +106,7 @@ class NeutronPodVIFDriver(base.PodVIFDriver):
'fixed_ips': ovu.osvif_to_neutron_fixed_ips(subnets),
'device_owner': kl_const.DEVICE_OWNER,
'admin_state_up': True,
'binding:host_id': utils.get_host_id(pod)}
'binding_host_id': utils.get_host_id(pod)}
# if unbound argument is set to true, it means the port requested
# should not be bound and not associated to the pod. Thus the port dict
@ -137,7 +123,4 @@ class NeutronPodVIFDriver(base.PodVIFDriver):
if security_groups:
port_req_body['security_groups'] = security_groups
return {'port': port_req_body}
def _get_vif_plugin(self, port):
return port.get('binding:vif_type')
return port_req_body

View File

@ -595,7 +595,7 @@ class NeutronVIFPool(BaseVIFPool):
# recovering in the case of multi pools
if available_subports.get(port['id']):
continue
vif_plugin = self._drv_vif._get_vif_plugin(port)
vif_plugin = port.get('binding:vif_type')
port_host = port['binding:host_id']
if not vif_plugin or not port_host:
# NOTE(ltomasbo): kuryr-controller is running without the

View File

@ -239,18 +239,9 @@ def neutron_to_osvif_vif_ovs(vif_plugin, os_port, subnets):
:param subnets: subnet mapping as returned by PodSubnetsDriver.get_subnets
:return: os-vif VIF object
"""
try:
# TODO(gryf): get rid of the except part after neutron_vif plugin is
# migrated to the openstacksdk.
port_id = os_port.id
mac_address = os_port.mac_address
details = os_port.binding_vif_details or {}
except AttributeError:
port_id = os_port['id']
mac_address = os_port['mac_address']
details = os_port.get('binding:vif_details', {})
profile = osv_vif.VIFPortProfileOpenVSwitch(interface_id=port_id)
profile = osv_vif.VIFPortProfileOpenVSwitch(interface_id=os_port.id)
details = os_port.binding_vif_details or {}
ovs_bridge = details.get('bridge_name',
config.CONF.neutron_defaults.ovs_bridge)
if not ovs_bridge:
@ -261,8 +252,8 @@ def neutron_to_osvif_vif_ovs(vif_plugin, os_port, subnets):
if details.get('ovs_hybrid_plug'):
vif = osv_vif.VIFBridge(
id=port_id,
address=mac_address,
id=os_port.id,
address=os_port.mac_address,
network=network,
has_traffic_filtering=details.get('port_filter', False),
preserve_on_delete=False,
@ -273,8 +264,8 @@ def neutron_to_osvif_vif_ovs(vif_plugin, os_port, subnets):
bridge_name=_get_ovs_hybrid_bridge_name(os_port))
else:
vif = osv_vif.VIFOpenVSwitch(
id=port_id,
address=mac_address,
id=os_port.id,
address=os_port.mac_address,
network=network,
has_traffic_filtering=details.get('port_filter', False),
preserve_on_delete=False,

View File

@ -16,7 +16,8 @@
import mock
from kuryr.lib import constants as kl_const
from neutronclient.common import exceptions as n_exc
import munch
from openstack import exceptions as os_exc
from oslo_config import cfg as oslo_cfg
from kuryr_kubernetes import constants
@ -33,36 +34,35 @@ class NeutronPodVIFDriver(test_base.TestCase):
def test_request_vif(self, m_to_vif):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
os_net = self.useFixture(k_fix.MockNetworkClient()).client
pod = mock.sentinel.pod
project_id = mock.sentinel.project_id
subnets = mock.sentinel.subnets
security_groups = mock.sentinel.security_groups
port = {'id': '910b1183-1f4a-450a-a298-0e80ad06ec8b'}
port_request = mock.sentinel.port_request
port = munch.Munch({'id': '910b1183-1f4a-450a-a298-0e80ad06ec8b'})
port_request = {'fake_req': mock.sentinel.port_request}
vif = mock.sentinel.vif
vif_plugin = mock.sentinel.vif_plugin
port.binding_vif_type = vif_plugin
m_to_vif.return_value = vif
m_driver._get_port_request.return_value = port_request
m_driver._get_vif_plugin.return_value = vif_plugin
neutron.create_port.return_value = {'port': port}
os_net.create_port.return_value = port
self.assertEqual(vif, cls.request_vif(m_driver, pod, project_id,
subnets, security_groups))
m_driver._get_port_request.assert_called_once_with(
pod, project_id, subnets, security_groups)
neutron.create_port.assert_called_once_with(port_request)
m_driver._get_vif_plugin.assert_called_once_with(port)
os_net.create_port.assert_called_once_with(**port_request)
m_to_vif.assert_called_once_with(vif_plugin, port, subnets)
@mock.patch('kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif')
def test_request_vifs(self, m_to_vif):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
os_net = self.useFixture(k_fix.MockNetworkClient()).client
pod = mock.sentinel.pod
project_id = mock.sentinel.project_id
@ -72,13 +72,13 @@ class NeutronPodVIFDriver(test_base.TestCase):
port_request = mock.sentinel.port_request
m_driver._get_port_request.return_value = port_request
port = {'id': '910b1183-1f4a-450a-a298-0e80ad06ec8b'}
port = munch.Munch({'id': '910b1183-1f4a-450a-a298-0e80ad06ec8b'})
vif_plugin = mock.sentinel.vif_plugin
port.binding_vif_type = vif_plugin
vif = mock.sentinel.vif
bulk_rq = {'ports': [port_request for _ in range(num_ports)]}
neutron.create_port.return_value = {'ports': [port, port]}
m_driver._get_vif_plugin.return_value = vif_plugin
os_net.create_ports.return_value = (p for p in [port, port])
m_to_vif.return_value = vif
self.assertEqual([vif, vif], cls.request_vifs(
@ -86,8 +86,7 @@ class NeutronPodVIFDriver(test_base.TestCase):
m_driver._get_port_request.assert_called_once_with(
pod, project_id, subnets, security_groups, unbound=True)
neutron.create_port.assert_called_once_with(bulk_rq)
m_driver._get_vif_plugin.assert_called_once_with(port)
os_net.create_ports.assert_called_once_with(bulk_rq)
calls = [mock.call(vif_plugin, port, subnets),
mock.call(vif_plugin, port, subnets)]
m_to_vif.assert_has_calls(calls)
@ -96,7 +95,7 @@ class NeutronPodVIFDriver(test_base.TestCase):
def test_request_vifs_unbound(self, m_to_vif):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
os_net = self.useFixture(k_fix.MockNetworkClient()).client
pod = mock.sentinel.pod
project_id = mock.sentinel.project_id
@ -107,14 +106,15 @@ class NeutronPodVIFDriver(test_base.TestCase):
port_request = mock.sentinel.port_request
m_driver._get_port_request.return_value = port_request
port_id = mock.sentinel.port_id
port = {'id': port_id}
port1 = munch.Munch({'id': port_id, 'binding_vif_type': 'unbound'})
vif_plugin = mock.sentinel.vif_plugin
port2 = munch.Munch({'id': port_id, 'binding_vif_type': vif_plugin})
port1_1 = munch.Munch({'id': port_id, 'binding_vif_type': vif_plugin})
vif = mock.sentinel.vif
bulk_rq = {'ports': [port_request for _ in range(num_ports)]}
neutron.create_port.return_value = {'ports': [port, port]}
m_driver._get_vif_plugin.side_effect = ['unbound', vif_plugin]
neutron.show_port.return_value = {'port': port}
os_net.create_ports.return_value = (p for p in [port1, port2])
os_net.get_port.return_value = port1_1
m_to_vif.return_value = vif
self.assertEqual([vif, vif], cls.request_vifs(
@ -122,18 +122,17 @@ class NeutronPodVIFDriver(test_base.TestCase):
m_driver._get_port_request.assert_called_once_with(
pod, project_id, subnets, security_groups, unbound=True)
neutron.create_port.assert_called_once_with(bulk_rq)
self.assertEqual(m_driver._get_vif_plugin.call_count, 2)
neutron.show_port.assert_called_once_with(port_id)
calls = [mock.call(vif_plugin, port, subnets),
mock.call(vif_plugin, port, subnets)]
os_net.create_ports.assert_called_once_with(bulk_rq)
os_net.get_port.assert_called_once_with(port_id)
calls = [mock.call(vif_plugin, port1, subnets),
mock.call(vif_plugin, port2, subnets)]
m_to_vif.assert_has_calls(calls)
@mock.patch('kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif')
def test_request_vifs_exception(self, m_to_vif):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
os_net = self.useFixture(k_fix.MockNetworkClient()).client
pod = mock.sentinel.pod
project_id = mock.sentinel.project_id
@ -145,47 +144,45 @@ class NeutronPodVIFDriver(test_base.TestCase):
m_driver._get_port_request.return_value = port_request
bulk_rq = {'ports': [port_request for _ in range(num_ports)]}
neutron.create_port.side_effect = n_exc.NeutronClientException
os_net.create_ports.side_effect = os_exc.SDKException
self.assertRaises(n_exc.NeutronClientException, cls.request_vifs,
self.assertRaises(os_exc.SDKException, cls.request_vifs,
m_driver, pod, project_id, subnets,
security_groups, num_ports)
m_driver._get_port_request.assert_called_once_with(
pod, project_id, subnets, security_groups, unbound=True)
neutron.create_port.assert_called_once_with(bulk_rq)
m_driver._get_vif_plugin.assert_not_called()
os_net.create_ports.assert_called_once_with(bulk_rq)
m_to_vif.assert_not_called()
def test_release_vif(self):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
os_net = self.useFixture(k_fix.MockNetworkClient()).client
pod = mock.sentinel.pod
vif = mock.Mock()
cls.release_vif(m_driver, pod, vif)
neutron.delete_port.assert_called_once_with(vif.id)
os_net.delete_port.assert_called_once_with(vif.id)
def test_release_vif_not_found(self):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
os_net = self.useFixture(k_fix.MockNetworkClient()).client
pod = mock.sentinel.pod
vif = mock.Mock()
neutron.delete_port.side_effect = n_exc.PortNotFoundClient
cls.release_vif(m_driver, pod, vif)
neutron.delete_port.assert_called_once_with(vif.id)
os_net.delete_port.assert_called_once_with(vif.id)
def test_activate_vif(self):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
os_net = self.useFixture(k_fix.MockNetworkClient()).client
pod = mock.sentinel.pod
vif = mock.Mock()
@ -193,17 +190,17 @@ class NeutronPodVIFDriver(test_base.TestCase):
port = mock.MagicMock()
port.__getitem__.return_value = kl_const.PORT_STATUS_ACTIVE
neutron.show_port.return_value = {'port': port}
os_net.get_port.return_value = port
cls.activate_vif(m_driver, pod, vif)
neutron.show_port.assert_called_once_with(vif.id)
os_net.get_port.assert_called_once_with(vif.id)
self.assertTrue(vif.active)
def test_activate_vif_active(self):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
os_net = self.useFixture(k_fix.MockNetworkClient()).client
pod = mock.sentinel.pod
vif = mock.Mock()
@ -211,12 +208,12 @@ class NeutronPodVIFDriver(test_base.TestCase):
cls.activate_vif(m_driver, pod, vif)
neutron.show_port.assert_not_called()
os_net.get_port.assert_not_called()
def test_activate_vif_not_ready(self):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
os_net = self.useFixture(k_fix.MockNetworkClient()).client
pod = mock.sentinel.pod
vif = mock.Mock()
@ -224,7 +221,7 @@ class NeutronPodVIFDriver(test_base.TestCase):
port = mock.MagicMock()
port.__getitem__.return_value = kl_const.PORT_STATUS_DOWN
neutron.show_port.return_value = {'port': port}
os_net.get_port.return_value = port
self.assertRaises(k_exc.ResourceNotReady, cls.activate_vif,
m_driver, pod, vif)
@ -254,21 +251,21 @@ class NeutronPodVIFDriver(test_base.TestCase):
True,
group='kubernetes')
expected = {'port': {'project_id': project_id,
'name': port_name,
'network_id': network_id,
'fixed_ips': fixed_ips,
'device_owner': kl_const.DEVICE_OWNER,
'admin_state_up': True,
'binding:host_id': host_id}}
expected = {'project_id': project_id,
'name': port_name,
'network_id': network_id,
'fixed_ips': fixed_ips,
'device_owner': kl_const.DEVICE_OWNER,
'admin_state_up': True,
'binding_host_id': host_id}
if security_groups:
expected['port']['security_groups'] = security_groups
expected['security_groups'] = security_groups
if unbound:
expected['port']['name'] = constants.KURYR_PORT_NAME
expected['name'] = constants.KURYR_PORT_NAME
else:
expected['port']['device_id'] = device_id
expected['device_id'] = device_id
ret = cls._get_port_request(m_driver, pod, project_id, subnets,
security_groups, unbound)
@ -318,14 +315,6 @@ class NeutronPodVIFDriver(test_base.TestCase):
m_get_port_name, m_get_host_id,
m_get_network_id, unbound=True)
def test_get_vif_plugin(self):
cls = neutron_vif.NeutronPodVIFDriver
m_driver = mock.Mock(spec=cls)
vif_plugin = mock.sentinel.vif_plugin
port = {'binding:vif_type': vif_plugin}
self.assertEqual(vif_plugin, cls._get_vif_plugin(m_driver, port))
def test_get_port_name(self):
pod_name = mock.sentinel.pod_name
port_name = 'default/' + str(pod_name)

View File

@ -889,7 +889,7 @@ class NeutronVIFPool(test_base.TestCase):
filtered_ports = [port]
m_get_ports.return_value = filtered_ports
vif_plugin = mock.sentinel.plugin
m_driver._drv_vif._get_vif_plugin.return_value = vif_plugin
port['binding:vif_type'] = vif_plugin
oslo_cfg.CONF.set_override('port_debug',
False,
@ -915,7 +915,6 @@ class NeutronVIFPool(test_base.TestCase):
m_get_ports.assert_called_once()
m_get_subnet.assert_called_with(subnet_id)
m_driver._drv_vif._get_vif_plugin.assert_called_once_with(port)
m_to_osvif.assert_called_once_with(vif_plugin, port, subnet)
self.assertEqual(m_driver._existing_vifs[port_id], vif)