Merge "NSX|V3 support different credentials for the NSX manages"

This commit is contained in:
Jenkins 2016-09-29 11:47:00 +00:00 committed by Gerrit Code Review
commit a3b17e2441
4 changed files with 66 additions and 25 deletions

View File

@ -0,0 +1,7 @@
---
prelude: >
The NSX-v3 plugin supports different credentials for the NSX managers.
features:
The nsxv3 configuration parameters ca_file, nsx_api_user & nsx_api_password
are now lists, in order to support different credentials for each of the
NSX managers.

View File

@ -246,15 +246,15 @@ nsx_common_opts = [
] ]
nsx_v3_opts = [ nsx_v3_opts = [
cfg.StrOpt('nsx_api_user', cfg.ListOpt('nsx_api_user',
deprecated_name='nsx_user', deprecated_name='nsx_user',
default='admin', default=['admin'],
help=_('User name for the NSX manager')), help=_('User names for the NSX managers')),
cfg.StrOpt('nsx_api_password', cfg.ListOpt('nsx_api_password',
deprecated_name='nsx_password', deprecated_name='nsx_password',
default='default', default=['default'],
secret=True, secret=True,
help=_('Password for the NSX manager')), help=_('Passwords for the NSX managers')),
cfg.ListOpt('nsx_api_managers', cfg.ListOpt('nsx_api_managers',
default=[], default=[],
deprecated_name='nsx_manager', deprecated_name='nsx_manager',
@ -291,10 +291,10 @@ nsx_v3_opts = [
default=10, default=10,
help=_('Maximum number of times to retry API requests upon ' help=_('Maximum number of times to retry API requests upon '
'stale revision errors.')), 'stale revision errors.')),
cfg.StrOpt('ca_file', cfg.ListOpt('ca_file',
help=_('Specify a CA bundle file to use in verifying the NSX ' help=_('Specify a CA bundle files to use in verifying the NSX '
'Manager server certificate. This option is ignored if ' 'Managers server certificate. This option is ignored '
'"insecure" is set to True. If "insecure" is set to ' 'if "insecure" is set to True. If "insecure" is set to '
'False and ca_file is unset, the system root CAs will ' 'False and ca_file is unset, the system root CAs will '
'be used to verify the server certificate.')), 'be used to verify the server certificate.')),
cfg.BoolOpt('insecure', cfg.BoolOpt('insecure',

View File

@ -124,14 +124,14 @@ class NSXRequestsHTTPProvider(AbstractHTTPProvider):
def new_connection(self, cluster_api, provider): def new_connection(self, cluster_api, provider):
session = TimeoutSession(cluster_api.http_timeout, session = TimeoutSession(cluster_api.http_timeout,
cluster_api.http_read_timeout) cluster_api.http_read_timeout)
session.auth = (cluster_api.username, cluster_api.password) session.auth = (provider.username, provider.password)
# NSX v3 doesn't use redirects # NSX v3 doesn't use redirects
session.max_redirects = 0 session.max_redirects = 0
session.verify = not cluster_api.insecure session.verify = not cluster_api.insecure
if session.verify and cluster_api.ca_file: if session.verify and provider.ca_file:
# verify using the said ca bundle path # verify using the said ca bundle path
session.verify = cluster_api.ca_file session.verify = provider.ca_file
# we are pooling with eventlet in the cluster class # we are pooling with eventlet in the cluster class
adapter = adapters.HTTPAdapter( adapter = adapters.HTTPAdapter(
@ -172,12 +172,15 @@ class EndpointState(object):
class Provider(object): class Provider(object):
"""Data holder for a provider which has a unique id """Data holder for a provider which has a unique id
and a connection URL. a connection URL, and the credential details.
""" """
def __init__(self, provider_id, provider_url): def __init__(self, provider_id, provider_url, username, password, ca_file):
self.id = provider_id self.id = provider_id
self.url = provider_url self.url = provider_url
self.username = username
self.password = password
self.ca_file = ca_file
def __str__(self): def __str__(self):
return str(self.url) return str(self.url)
@ -459,11 +462,15 @@ class NSXClusteredAPI(ClusteredAPI):
http_read_timeout=None, http_read_timeout=None,
conn_idle_timeout=None, conn_idle_timeout=None,
http_provider=None): http_provider=None):
self.username = username or cfg.CONF.nsx_v3.nsx_api_user
self.password = password or cfg.CONF.nsx_v3.nsx_api_password
self.retries = retries or cfg.CONF.nsx_v3.http_retries self.retries = retries or cfg.CONF.nsx_v3.http_retries
self.insecure = insecure or cfg.CONF.nsx_v3.insecure self.insecure = insecure or cfg.CONF.nsx_v3.insecure
self.ca_file = ca_file or cfg.CONF.nsx_v3.ca_file
# username, password & ca_file may be lists, in order to support
# different credentials per nsx manager
self._username = username or cfg.CONF.nsx_v3.nsx_api_user
self._password = password or cfg.CONF.nsx_v3.nsx_api_password
self._ca_file = ca_file or cfg.CONF.nsx_v3.ca_file
self.conns_per_pool = (concurrent_connections or self.conns_per_pool = (concurrent_connections or
cfg.CONF.nsx_v3.concurrent_connections) cfg.CONF.nsx_v3.concurrent_connections)
self.http_timeout = http_timeout or cfg.CONF.nsx_v3.http_timeout self.http_timeout = http_timeout or cfg.CONF.nsx_v3.http_timeout
@ -494,14 +501,40 @@ class NSXClusteredAPI(ClusteredAPI):
conf_urls = cfg.CONF.nsx_v3.nsx_api_managers[:] conf_urls = cfg.CONF.nsx_v3.nsx_api_managers[:]
urls = [] urls = []
providers = [] providers = []
provider_index = -1
for conf_url in conf_urls: for conf_url in conf_urls:
provider_index += 1
conf_url = _schemed_url(conf_url) conf_url = _schemed_url(conf_url)
if conf_url in urls: if conf_url in urls:
LOG.warning(_LW("'%s' already defined in configuration file. " LOG.warning(_LW("'%s' already defined in configuration file. "
"Skipping."), urlparse.urlunparse(conf_url)) "Skipping."), urlparse.urlunparse(conf_url))
continue continue
urls.append(conf_url) urls.append(conf_url)
providers.append(Provider( providers.append(
conf_url.netloc, urlparse.urlunparse(conf_url))) Provider(
conf_url.netloc,
urlparse.urlunparse(conf_url),
self.username(provider_index),
self.password(provider_index),
self.ca_file(provider_index)))
return providers return providers
def _attribute_by_index(self, scalar_or_list, index):
if isinstance(scalar_or_list, list):
if not len(scalar_or_list):
return None
if len(scalar_or_list) > index:
return scalar_or_list[index]
# if not long enough - use the first one as default
return scalar_or_list[0]
# this is a scalar
return scalar_or_list
def username(self, index):
return self._attribute_by_index(self._username, index)
def password(self, index):
return self._attribute_by_index(self._password, index)
def ca_file(self, index):
return self._attribute_by_index(self._ca_file, index)

View File

@ -39,16 +39,17 @@ class RequestsHTTPProviderTestCase(unittest.TestCase):
def test_new_connection(self): def test_new_connection(self):
mock_api = mock.Mock() mock_api = mock.Mock()
mock_api.username = 'nsxuser' mock_api._username = 'nsxuser'
mock_api.password = 'nsxpassword' mock_api._password = 'nsxpassword'
mock_api.retries = 100 mock_api.retries = 100
mock_api.insecure = True mock_api.insecure = True
mock_api.ca_file = None mock_api._ca_file = None
mock_api.http_timeout = 99 mock_api.http_timeout = 99
mock_api.conn_idle_timeout = 39 mock_api.conn_idle_timeout = 39
provider = cluster.NSXRequestsHTTPProvider() provider = cluster.NSXRequestsHTTPProvider()
session = provider.new_connection( session = provider.new_connection(
mock_api, cluster.Provider('9.8.7.6', 'https://9.8.7.6')) mock_api, cluster.Provider('9.8.7.6', 'https://9.8.7.6',
'nsxuser', 'nsxpassword', None))
self.assertEqual(session.auth, ('nsxuser', 'nsxpassword')) self.assertEqual(session.auth, ('nsxuser', 'nsxpassword'))
self.assertEqual(session.verify, False) self.assertEqual(session.verify, False)