Removed neutronclient option from metadata agent

The new RPC interface has proved itself for two cycles, I don't
recollect any serious issues with it, so let's just clean up the
obsolete neutronclient based fallback mechanism.

The metadata agent configuration documentation should be updated
to not require API configuration values for the agent to talk to
neutron-server.

DocImpact
Change-Id: I254c575c66214f50fb93a94c46c4c9caebfc2937
Closes-Bug: #1502947
This commit is contained in:
Ihar Hrachyshka 2015-10-05 17:46:33 +02:00
parent e805d7a73a
commit e5cd4a9f54
5 changed files with 49 additions and 290 deletions

View File

@ -2,20 +2,6 @@
# Show debugging output in log (sets DEBUG log level output)
# debug = True
# The Neutron user information for accessing the Neutron API.
auth_url = http://localhost:5000/v2.0
auth_region = RegionOne
# Turn off verification of the certificate for ssl
# auth_insecure = False
# Certificate Authority public key (CA cert) file for ssl
# auth_ca_cert =
admin_tenant_name = %SERVICE_TENANT_NAME%
admin_user = %SERVICE_USER%
admin_password = %SERVICE_PASSWORD%
# Network service endpoint type to pull from the keystone catalog
# endpoint_type = adminURL
# IP address used by Nova metadata server
# nova_metadata_ip = 127.0.0.1

View File

@ -16,7 +16,6 @@ import hashlib
import hmac
import httplib2
from neutronclient.v2_0 import client
from oslo_config import cfg
from oslo_log import log as logging
import oslo_messaging
@ -75,7 +74,6 @@ class MetadataProxyHandler(object):
def __init__(self, conf):
self.conf = conf
self.auth_info = {}
if self.conf.cache_url:
self._cache = cache.get_cache(self.conf.cache_url)
else:
@ -83,28 +81,6 @@ class MetadataProxyHandler(object):
self.plugin_rpc = MetadataPluginAPI(topics.PLUGIN)
self.context = context.get_admin_context_without_session()
# Use RPC by default
self.use_rpc = True
def _get_neutron_client(self):
params = {
'username': self.conf.admin_user,
'password': self.conf.admin_password,
'tenant_name': self.conf.admin_tenant_name,
'auth_url': self.conf.auth_url,
'auth_strategy': self.conf.auth_strategy,
'region_name': self.conf.auth_region,
'token': self.auth_info.get('auth_token'),
'insecure': self.conf.auth_insecure,
'ca_cert': self.conf.auth_ca_cert,
}
if self.conf.endpoint_url:
params['endpoint_url'] = self.conf.endpoint_url
else:
params['endpoint_url'] = self.auth_info.get('endpoint_url')
params['endpoint_type'] = self.conf.endpoint_type
return client.Client(**params)
@webob.dec.wsgify(RequestClass=webob.Request)
def __call__(self, req):
@ -126,19 +102,9 @@ class MetadataProxyHandler(object):
def _get_ports_from_server(self, router_id=None, ip_address=None,
networks=None):
"""Either get ports from server by RPC or fallback to neutron client"""
"""Get ports from server."""
filters = self._get_port_filters(router_id, ip_address, networks)
if self.use_rpc:
try:
return self.plugin_rpc.get_ports(self.context, filters)
except (oslo_messaging.MessagingException, AttributeError):
# TODO(obondarev): remove fallback once RPC is proven
# to work fine with metadata agent (K or L release at most)
LOG.warning(_LW('Server does not support metadata RPC, '
'fallback to using neutron client'))
self.use_rpc = False
return self._get_ports_using_client(filters)
return self.plugin_rpc.get_ports(self.context, filters)
def _get_port_filters(self, router_id=None, ip_address=None,
networks=None):
@ -171,19 +137,6 @@ class MetadataProxyHandler(object):
return self._get_ports_from_server(networks=networks,
ip_address=remote_address)
def _get_ports_using_client(self, filters):
# reformat filters for neutron client
if 'device_id' in filters:
filters['device_id'] = filters['device_id'][0]
if 'fixed_ips' in filters:
filters['fixed_ips'] = [
'ip_address=%s' % filters['fixed_ips']['ip_address'][0]]
client = self._get_neutron_client()
ports = client.list_ports(**filters)
self.auth_info = client.get_auth_info()
return ports['ports']
def _get_ports(self, remote_address, network_id=None, router_id=None):
"""Search for all ports that contain passed ip address and belongs to
given network.

View File

@ -50,34 +50,9 @@ DRIVER_OPTS = [
METADATA_PROXY_HANDLER_OPTS = [
cfg.StrOpt('admin_user',
help=_("Admin user")),
cfg.StrOpt('admin_password',
help=_("Admin password"),
secret=True),
cfg.StrOpt('admin_tenant_name',
help=_("Admin tenant name")),
cfg.StrOpt('auth_url',
help=_("Authentication URL")),
cfg.StrOpt('auth_strategy', default='keystone',
help=_("The type of authentication to use")),
cfg.StrOpt('auth_region',
help=_("Authentication region")),
cfg.BoolOpt('auth_insecure',
default=False,
help=_("Turn off verification of the certificate for"
" ssl")),
cfg.StrOpt('auth_ca_cert',
help=_("Certificate Authority public key (CA cert) "
"file for ssl")),
cfg.StrOpt('endpoint_type',
default='adminURL',
help=_("Network service endpoint type to pull from "
"the keystone catalog")),
cfg.StrOpt('endpoint_url',
default=None,
help=_("Neutron endpoint URL, if not set will use endpoint "
"from the keystone catalog along with endpoint_type")),
cfg.StrOpt('nova_metadata_ip', default='127.0.0.1',
help=_("IP address used by Nova metadata server.")),
cfg.IntOpt('nova_metadata_port',

View File

@ -20,22 +20,13 @@ from neutron.agent.linux import utils as agent_utils
from neutron.agent.metadata import agent
from neutron.agent.metadata import config
from neutron.agent import metadata_agent
from neutron.common import constants
from neutron.common import constants as n_const
from neutron.common import utils
from neutron.tests import base
from neutronclient.v2_0 import client
class FakeConf(object):
admin_user = 'neutron'
admin_password = 'password'
admin_tenant_name = 'tenant'
auth_url = 'http://127.0.0.1'
auth_strategy = 'keystone'
auth_region = 'region'
auth_insecure = False
auth_ca_cert = None
endpoint_type = 'adminURL'
nova_metadata_ip = '9.9.9.9'
nova_metadata_port = 8775
metadata_proxy_shared_secret = 'secret'
@ -44,55 +35,12 @@ class FakeConf(object):
nova_client_cert = 'nova_cert'
nova_client_priv_key = 'nova_priv_key'
cache_url = ''
endpoint_url = None
class FakeConfCache(FakeConf):
cache_url = 'memory://?default_ttl=5'
class FakeConfEndpoint(FakeConf):
endpoint_url = 'http://127.0.0.0:8776'
class TestNeutronClient(base.BaseTestCase):
fake_conf = FakeConf
expected_params = {
'username': 'neutron',
'region_name': 'region',
'ca_cert': None,
'tenant_name': 'tenant',
'insecure': False,
'token': None,
'endpoint_type': 'adminURL',
'auth_url': 'http://127.0.0.1',
'password': 'password',
'endpoint_url': None,
'auth_strategy': 'keystone',
}
def test_client_params(self):
handler = agent.MetadataProxyHandler(self.fake_conf)
with mock.patch.object(
client.Client, "__init__", return_value=None) as mock_init:
handler._get_neutron_client()
mock_init.assert_called_once_with(**self.expected_params)
def test_client_with_endpoint_url(self):
fake_conf = FakeConfEndpoint
handler = agent.MetadataProxyHandler(fake_conf)
expected_params = self.expected_params.copy()
del expected_params['endpoint_type']
expected_params['endpoint_url'] = 'http://127.0.0.0:8776'
with mock.patch.object(
client.Client, "__init__", return_value=None) as mock_init:
handler._get_neutron_client()
mock_init.assert_called_once_with(**expected_params)
class TestMetadataProxyHandlerBase(base.BaseTestCase):
fake_conf = FakeConf
@ -111,7 +59,7 @@ class TestMetadataProxyHandlerRpc(TestMetadataProxyHandlerBase):
ip = '1.2.3.4'
networks = ('net_id1', 'net_id2')
expected = {'device_id': [router_id],
'device_owner': constants.ROUTER_INTERFACE_OWNERS,
'device_owner': n_const.ROUTER_INTERFACE_OWNERS,
'network_id': networks,
'fixed_ips': {'ip_address': [ip]}}
actual = self.handler._get_port_filters(router_id, ip, networks)
@ -135,28 +83,10 @@ class TestMetadataProxyHandlerRpc(TestMetadataProxyHandlerBase):
ports = self.handler._get_ports_for_remote_address(ip, networks)
self.assertEqual(expected, ports)
def test_get_ports_using_rpc_fallback_to_client(self):
ip = '1.1.1.1'
networks = ('network_id1', 'network_id2')
self.handler.plugin_rpc.get_ports.side_effect = AttributeError
with mock.patch('neutronclient.v2_0.client.Client') as neutron_client:
mock_list_ports = neutron_client.return_value.list_ports
expected_ports = {'ports': ['expected_port']}
mock_list_ports.return_value = expected_ports
ports = self.handler._get_ports_from_server(ip_address=ip,
networks=networks)
self.assertEqual(expected_ports['ports'], ports)
class TestMetadataProxyHandlerCache(TestMetadataProxyHandlerBase):
fake_conf = FakeConfCache
def setUp(self):
super(TestMetadataProxyHandlerCache, self).setUp()
self.qclient_p = mock.patch('neutronclient.v2_0.client.Client')
self.qclient = self.qclient_p.start()
self.handler.use_rpc = False
def test_call(self):
req = mock.Mock()
with mock.patch.object(self.handler,
@ -188,57 +118,57 @@ class TestMetadataProxyHandlerCache(TestMetadataProxyHandlerBase):
def test_get_router_networks(self):
router_id = 'router-id'
expected = ('network_id1', 'network_id2')
ports = {'ports': [{'network_id': 'network_id1', 'something': 42},
{'network_id': 'network_id2',
'something_else': 32}],
'not_used': [1, 2, 3]}
mock_list_ports = self.qclient.return_value.list_ports
mock_list_ports.return_value = ports
ports = [{'network_id': 'network_id1', 'something': 42},
{'network_id': 'network_id2', 'something_else': 32}]
mock_get_ports = self.handler.plugin_rpc.get_ports
mock_get_ports.return_value = ports
networks = self.handler._get_router_networks(router_id)
mock_list_ports.assert_called_once_with(
device_id=router_id,
device_owner=constants.ROUTER_INTERFACE_OWNERS)
mock_get_ports.assert_called_once_with(
mock.ANY,
{'device_id': [router_id],
'device_owner': n_const.ROUTER_INTERFACE_OWNERS})
self.assertEqual(expected, networks)
def _test_get_router_networks_twice_helper(self):
router_id = 'router-id'
ports = {'ports': [{'network_id': 'network_id1', 'something': 42}],
'not_used': [1, 2, 3]}
ports = [{'network_id': 'network_id1', 'something': 42}]
expected_networks = ('network_id1',)
with mock.patch(
'oslo_utils.timeutils.utcnow_ts', return_value=0):
mock_list_ports = self.qclient.return_value.list_ports
mock_list_ports.return_value = ports
mock_get_ports = self.handler.plugin_rpc.get_ports
mock_get_ports.return_value = ports
networks = self.handler._get_router_networks(router_id)
mock_list_ports.assert_called_once_with(
device_id=router_id,
device_owner=constants.ROUTER_INTERFACE_OWNERS)
mock_get_ports.assert_called_once_with(
mock.ANY,
{'device_id': [router_id],
'device_owner': n_const.ROUTER_INTERFACE_OWNERS})
self.assertEqual(expected_networks, networks)
networks = self.handler._get_router_networks(router_id)
def test_get_router_networks_twice(self):
self._test_get_router_networks_twice_helper()
self.assertEqual(
1, self.qclient.return_value.list_ports.call_count)
1, self.handler.plugin_rpc.get_ports.call_count)
def _get_ports_for_remote_address_cache_hit_helper(self):
remote_address = 'remote_address'
networks = ('net1', 'net2')
fixed_ips = ["ip_address=%s" % remote_address]
mock_list_ports = self.qclient.return_value.list_ports
mock_list_ports.return_value = {'ports': [{'network_id': 'net1',
'something': 42}]}
mock_get_ports = self.handler.plugin_rpc.get_ports
mock_get_ports.return_value = [{'network_id': 'net1', 'something': 42}]
self.handler._get_ports_for_remote_address(remote_address, networks)
mock_list_ports.assert_called_once_with(
network_id=networks, fixed_ips=fixed_ips)
self.assertEqual(1, mock_list_ports.call_count)
mock_get_ports.assert_called_once_with(
mock.ANY,
{'network_id': networks,
'fixed_ips': {'ip_address': [remote_address]}}
)
self.assertEqual(1, mock_get_ports.call_count)
self.handler._get_ports_for_remote_address(remote_address,
networks)
def test_get_ports_for_remote_address_cache_hit(self):
self._get_ports_for_remote_address_cache_hit_helper()
self.assertEqual(
1, self.qclient.return_value.list_ports.call_count)
1, self.handler.plugin_rpc.get_ports.call_count)
def test_get_ports_network_id(self):
network_id = 'network-id'
@ -288,46 +218,32 @@ class TestMetadataProxyHandlerCache(TestMetadataProxyHandlerBase):
headers['X-Forwarded-For'] = remote_address
req = mock.Mock(headers=headers)
def mock_list_ports(*args, **kwargs):
return {'ports': list_ports_retval.pop(0)}
def mock_get_ports(*args, **kwargs):
return list_ports_retval.pop(0)
self.qclient.return_value.list_ports.side_effect = mock_list_ports
self.qclient.return_value.get_auth_info.return_value = {
'auth_token': None, 'endpoint_url': None}
self.handler.plugin_rpc.get_ports.side_effect = mock_get_ports
instance_id, tenant_id = self.handler._get_instance_and_tenant_id(req)
new_qclient_call = mock.call(
username=FakeConf.admin_user,
tenant_name=FakeConf.admin_tenant_name,
region_name=FakeConf.auth_region,
auth_url=FakeConf.auth_url,
password=FakeConf.admin_password,
auth_strategy=FakeConf.auth_strategy,
token=None,
insecure=FakeConf.auth_insecure,
ca_cert=FakeConf.auth_ca_cert,
endpoint_url=None,
endpoint_type=FakeConf.endpoint_type)
expected = []
if router_id:
expected.extend([
new_qclient_call,
mock.call().list_ports(
device_id=router_id,
device_owner=constants.ROUTER_INTERFACE_OWNERS
),
mock.call().get_auth_info()
])
expected.append(
mock.call(
mock.ANY,
{'device_id': [router_id],
'device_owner': n_const.ROUTER_INTERFACE_OWNERS}
)
)
expected.extend([
new_qclient_call,
mock.call().list_ports(
network_id=networks, fixed_ips=['ip_address=192.168.1.1']),
mock.call().get_auth_info()
])
expected.append(
mock.call(
mock.ANY,
{'network_id': networks,
'fixed_ips': {'ip_address': ['192.168.1.1']}}
)
)
self.qclient.assert_has_calls(expected)
self.handler.plugin_rpc.get_ports.assert_has_calls(expected)
return (instance_id, tenant_id)
@ -401,65 +317,6 @@ class TestMetadataProxyHandlerCache(TestMetadataProxyHandlerBase):
(None, None)
)
def test_auth_info_cache(self):
router_id = 'the_id'
list_ports = [
[{'network_id': 'net1'}],
[{'device_id': 'did', 'tenant_id': 'tid', 'network_id': 'net1'}]]
def update_get_auth_info(*args, **kwargs):
self.qclient.return_value.get_auth_info.return_value = {
'auth_token': 'token', 'endpoint_url': 'uri'}
return {'ports': list_ports.pop(0)}
self.qclient.return_value.list_ports.side_effect = update_get_auth_info
new_qclient_call = mock.call(
username=FakeConf.admin_user,
tenant_name=FakeConf.admin_tenant_name,
region_name=FakeConf.auth_region,
auth_url=FakeConf.auth_url,
password=FakeConf.admin_password,
auth_strategy=FakeConf.auth_strategy,
token=None,
insecure=FakeConf.auth_insecure,
ca_cert=FakeConf.auth_ca_cert,
endpoint_url=None,
endpoint_type=FakeConf.endpoint_type)
cached_qclient_call = mock.call(
username=FakeConf.admin_user,
tenant_name=FakeConf.admin_tenant_name,
region_name=FakeConf.auth_region,
auth_url=FakeConf.auth_url,
password=FakeConf.admin_password,
auth_strategy=FakeConf.auth_strategy,
token='token',
insecure=FakeConf.auth_insecure,
ca_cert=FakeConf.auth_ca_cert,
endpoint_url='uri',
endpoint_type=FakeConf.endpoint_type)
headers = {'X-Forwarded-For': '192.168.1.10',
'X-Neutron-Router-ID': router_id}
req = mock.Mock(headers=headers)
self.handler._get_instance_and_tenant_id(req)
expected = [
new_qclient_call,
mock.call().list_ports(
device_id=router_id,
device_owner=constants.ROUTER_INTERFACE_OWNERS
),
mock.call().get_auth_info(),
cached_qclient_call,
mock.call().list_ports(network_id=('net1',),
fixed_ips=['ip_address=192.168.1.10']),
mock.call().get_auth_info(),
]
self.qclient.assert_has_calls(expected)
def _proxy_request_test_helper(self, response_code=200, method='GET'):
hdrs = {'X-Forwarded-For': '8.8.8.8'}
body = 'body'
@ -547,12 +404,12 @@ class TestMetadataProxyHandlerNoCache(TestMetadataProxyHandlerCache):
def test_get_router_networks_twice(self):
self._test_get_router_networks_twice_helper()
self.assertEqual(
2, self.qclient.return_value.list_ports.call_count)
2, self.handler.plugin_rpc.get_ports.call_count)
def test_get_ports_for_remote_address_cache_hit(self):
self._get_ports_for_remote_address_cache_hit_helper()
self.assertEqual(
2, self.qclient.return_value.list_ports.call_count)
2, self.handler.plugin_rpc.get_ports.call_count)
class TestUnixDomainMetadataProxy(base.BaseTestCase):

View File

@ -24,18 +24,6 @@ from neutron.tests import base
from neutron import wsgi
class FakeConf(object):
admin_user = 'neutron'
admin_password = 'password'
admin_tenant_name = 'tenant'
auth_url = 'http://127.0.0.1'
auth_strategy = 'keystone'
auth_region = 'region'
nova_metadata_ip = '9.9.9.9'
nova_metadata_port = 8775
metadata_proxy_shared_secret = 'secret'
class TestNetworkMetadataProxyHandler(base.BaseTestCase):
def setUp(self):
super(TestNetworkMetadataProxyHandler, self).setUp()