Allow user specified endpoint_type in config

* Use user specified endpoint_type (public|internal|admin) for creating
  openstack clients in Rally

Change-Id: I4af74d21417045df966c7fbe1ee735b15a36ae5f
Closes-Bug: #1351567
This commit is contained in:
Rohan Kanade 2014-09-30 12:31:40 +02:00
parent a11b217114
commit b3bfe485bc
13 changed files with 70 additions and 38 deletions

View File

@ -2,7 +2,7 @@
"type": "ExistingCloud", "type": "ExistingCloud",
"auth_url": "http://example.net:5000/v3/", "auth_url": "http://example.net:5000/v3/",
"region_name": "RegionOne", "region_name": "RegionOne",
"use_public_urls": true, "endpoint_type": "internal",
"admin_port": 35357, "admin_port": 35357,
"admin": { "admin": {
"username": "admin", "username": "admin",

View File

@ -2,7 +2,7 @@
"type": "ExistingCloud", "type": "ExistingCloud",
"auth_url": "http://example.net:5000/v2.0/", "auth_url": "http://example.net:5000/v2.0/",
"region_name": "RegionOne", "region_name": "RegionOne",
"use_public_urls": true, "endpoint_type": "internal",
"admin_port": 35357, "admin_port": 35357,
"admin": { "admin": {
"username": "admin", "username": "admin",

View File

@ -62,7 +62,7 @@ This engine in fact does not deploy anything, but uses an existing OpenStack ins
"username": "admin", "username": "admin",
"password": "password", "password": "password",
"tenant_name": "admin", "tenant_name": "admin",
"use_public_urls": True "endpoint_type": "internal"
} }
} }
@ -80,14 +80,14 @@ Or using keystone v3 API endpoint:
"project_domain_name": "qa, "project_domain_name": "qa,
"password": "password, "password": "password,
"region_name": "RegionOne, "region_name": "RegionOne,
"use_public_urls": False, "endpoint_type": "internal",
"admin_port": 35357 "admin_port": 35357
} }
} }
.. ..
*use_public_urls* option will be used later for switching access method to the cloud. *endpoint_type* option will be used later for selecting access method to the cloud.
Because in some use-cases cloud may be accessible only by public endpoints. Users can select from "public", "internal", "admin" access methods.

View File

@ -172,7 +172,7 @@ class DeploymentCommands(object):
:param deploy_id: a UUID of the deployment :param deploy_id: a UUID of the deployment
""" """
headers = ['auth_url', 'username', 'password', 'tenant_name', headers = ['auth_url', 'username', 'password', 'tenant_name',
'region_name', 'use_public_urls', 'admin_port'] 'region_name', 'endpoint_type', 'admin_port']
table_rows = [] table_rows = []
deployment = db.deployment_get(deploy_id) deployment = db.deployment_get(deploy_id)

View File

@ -68,6 +68,12 @@ class _EndpointPermission(utils.ImmutableMixin, utils.EnumMixin):
USER = "user" USER = "user"
class _EndpointType(utils.ImmutableMixin, utils.EnumMixin):
INTERNAL = "internal"
ADMIN = "admin"
PUBLIC = "public"
class _RunnerType(utils.ImmutableMixin, utils.EnumMixin): class _RunnerType(utils.ImmutableMixin, utils.EnumMixin):
SERIAL = "serial" SERIAL = "serial"
CONSTANT = "constant" CONSTANT = "constant"
@ -148,3 +154,4 @@ EndpointPermission = _EndpointPermission()
RunnerType = _RunnerType() RunnerType = _RunnerType()
ServiceType = _ServiceType() ServiceType = _ServiceType()
Service = _Service() Service = _Service()
EndpointType = _EndpointType()

View File

@ -27,7 +27,7 @@ class ExistingCloud(engine.EngineFactory):
"type": "ExistingCloud", "type": "ExistingCloud",
"auth_url": "http://localhost:5000/v2.0/", "auth_url": "http://localhost:5000/v2.0/",
"region_name": "RegionOne", "region_name": "RegionOne",
"use_public_urls": true, "endpoint_type": "admin",
"admin_port": 35357, "admin_port": 35357,
"admin": { "admin": {
"username": "admin", "username": "admin",
@ -42,7 +42,7 @@ class ExistingCloud(engine.EngineFactory):
"type": "ExistingCloud", "type": "ExistingCloud",
"auth_url": "http://localhost:5000/v3/", "auth_url": "http://localhost:5000/v3/",
"region_name": "RegionOne", "region_name": "RegionOne",
"use_public_urls": false, "endpoint_type": "admin",
"admin_port": 35357, "admin_port": 35357,
"admin": { "admin": {
"username": "admin", "username": "admin",
@ -89,7 +89,10 @@ class ExistingCloud(engine.EngineFactory):
"type": {"type": "string"}, "type": {"type": "string"},
"auth_url": {"type": "string"}, "auth_url": {"type": "string"},
"region_name": {"type": "string"}, "region_name": {"type": "string"},
"use_public_urls": {"type": "boolean"}, "endpoint_type": {"type": "string",
"enum": [consts.EndpointType.ADMIN,
consts.EndpointType.INTERNAL,
consts.EndpointType.PUBLIC]},
"admin_port": { "admin_port": {
"type": "integer", "type": "integer",
"minimum": 2, "minimum": 2,
@ -119,7 +122,8 @@ class ExistingCloud(engine.EngineFactory):
tenant_name=user.get("project_name", user.get("tenant_name")), tenant_name=user.get("project_name", user.get("tenant_name")),
permission=permission, permission=permission,
region_name=common.get("region_name"), region_name=common.get("region_name"),
use_public_urls=common.get("use_public_urls", False), endpoint_type=common.get("endpoint_type",
consts.EndpointType.INTERNAL),
admin_port=common.get("admin_port", 35357), admin_port=common.get("admin_port", 35357),
domain_name=user.get("domain_name"), domain_name=user.get("domain_name"),
user_domain_name=user.get("user_domain_name", "Default"), user_domain_name=user.get("user_domain_name", "Default"),

View File

@ -20,8 +20,9 @@ class Endpoint(object):
def __init__(self, auth_url, username, password, tenant_name=None, def __init__(self, auth_url, username, password, tenant_name=None,
permission=consts.EndpointPermission.USER, permission=consts.EndpointPermission.USER,
region_name=None, use_public_urls=False, admin_port=35357, region_name=None, endpoint_type=consts.EndpointType.INTERNAL,
domain_name=None, user_domain_name='Default', admin_port=35357, domain_name=None,
user_domain_name='Default',
project_domain_name='Default'): project_domain_name='Default'):
self.auth_url = auth_url self.auth_url = auth_url
self.username = username self.username = username
@ -29,7 +30,7 @@ class Endpoint(object):
self.tenant_name = tenant_name self.tenant_name = tenant_name
self.permission = permission self.permission = permission
self.region_name = region_name self.region_name = region_name
self.use_public_urls = use_public_urls self.endpoint_type = endpoint_type
self.admin_port = admin_port self.admin_port = admin_port
self.domain_name = domain_name self.domain_name = domain_name
self.user_domain_name = user_domain_name self.user_domain_name = user_domain_name
@ -39,7 +40,7 @@ class Endpoint(object):
dct = {"auth_url": self.auth_url, "username": self.username, dct = {"auth_url": self.auth_url, "username": self.username,
"password": self.password, "tenant_name": self.tenant_name, "password": self.password, "tenant_name": self.tenant_name,
"region_name": self.region_name, "region_name": self.region_name,
"use_public_urls": self.use_public_urls, "endpoint_type": self.endpoint_type,
"admin_port": self.admin_port, "admin_port": self.admin_port,
"domain_name": self.domain_name, "domain_name": self.domain_name,
"user_domain_name": self.user_domain_name, "user_domain_name": self.user_domain_name,

View File

@ -97,7 +97,7 @@ class Clients(object):
"insecure": CONF.https_insecure, "cacert": CONF.https_cacert "insecure": CONF.https_insecure, "cacert": CONF.https_cacert
} }
kw = dict(self.endpoint.to_dict().items() + new_kw.items()) kw = dict(self.endpoint.to_dict().items() + new_kw.items())
if kw["use_public_urls"]: if kw["endpoint_type"] == consts.EndpointType.PUBLIC:
mgmt_url = urlparse.urlparse(kw["auth_url"]) mgmt_url = urlparse.urlparse(kw["auth_url"])
if mgmt_url.port != kw["admin_port"]: if mgmt_url.port != kw["admin_port"]:
kw["endpoint"] = "{0}://{1}:{2}{3}".format( kw["endpoint"] = "{0}://{1}:{2}{3}".format(
@ -136,7 +136,8 @@ class Clients(object):
"""Return nova client.""" """Return nova client."""
kc = self.keystone() kc = self.keystone()
compute_api_url = kc.service_catalog.url_for( compute_api_url = kc.service_catalog.url_for(
service_type='compute', endpoint_type='public', service_type='compute',
endpoint_type=self.endpoint.endpoint_type,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
client = nova.Client(version, client = nova.Client(version,
auth_token=kc.auth_token, auth_token=kc.auth_token,
@ -152,7 +153,8 @@ class Clients(object):
"""Return neutron client.""" """Return neutron client."""
kc = self.keystone() kc = self.keystone()
network_api_url = kc.service_catalog.url_for( network_api_url = kc.service_catalog.url_for(
service_type='network', endpoint_type='public', service_type='network',
endpoint_type=self.endpoint.endpoint_type,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
client = neutron.Client(version, client = neutron.Client(version,
token=kc.auth_token, token=kc.auth_token,
@ -167,7 +169,8 @@ class Clients(object):
"""Return glance client.""" """Return glance client."""
kc = self.keystone() kc = self.keystone()
image_api_url = kc.service_catalog.url_for( image_api_url = kc.service_catalog.url_for(
service_type='image', endpoint_type='public', service_type='image',
endpoint_type=self.endpoint.endpoint_type,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
client = glance.Client(version, client = glance.Client(version,
endpoint=image_api_url, endpoint=image_api_url,
@ -182,7 +185,8 @@ class Clients(object):
"""Return heat client.""" """Return heat client."""
kc = self.keystone() kc = self.keystone()
orchestration_api_url = kc.service_catalog.url_for( orchestration_api_url = kc.service_catalog.url_for(
service_type='orchestration', endpoint_type='public', service_type='orchestration',
endpoint_type=self.endpoint.endpoint_type,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
client = heat.Client(version, client = heat.Client(version,
endpoint=orchestration_api_url, endpoint=orchestration_api_url,
@ -202,7 +206,8 @@ class Clients(object):
cacert=CONF.https_cacert) cacert=CONF.https_cacert)
kc = self.keystone() kc = self.keystone()
volume_api_url = kc.service_catalog.url_for( volume_api_url = kc.service_catalog.url_for(
service_type='volume', endpoint_type='public', service_type='volume',
endpoint_type=self.endpoint.endpoint_type,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
client.client.management_url = volume_api_url client.client.management_url = volume_api_url
client.client.auth_token = kc.auth_token client.client.auth_token = kc.auth_token
@ -213,7 +218,8 @@ class Clients(object):
"""Return ceilometer client.""" """Return ceilometer client."""
kc = self.keystone() kc = self.keystone()
metering_api_url = kc.service_catalog.url_for( metering_api_url = kc.service_catalog.url_for(
service_type='metering', endpoint_type='public', service_type='metering',
endpoint_type=self.endpoint.endpoint_type,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
auth_token = kc.auth_token auth_token = kc.auth_token
if not hasattr(auth_token, '__call__'): if not hasattr(auth_token, '__call__'):
@ -233,7 +239,8 @@ class Clients(object):
"""Return Ironic client.""" """Return Ironic client."""
kc = self.keystone() kc = self.keystone()
baremetal_api_url = kc.service_catalog.url_for( baremetal_api_url = kc.service_catalog.url_for(
service_type='baremetal', endpoint_type='public', service_type='baremetal',
endpoint_type=self.endpoint.endpoint_type,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
client = ironic.get_client(version, client = ironic.get_client(version,
os_auth_token=kc.auth_token, os_auth_token=kc.auth_token,
@ -259,7 +266,8 @@ class Clients(object):
"""Return Zaqar client.""" """Return Zaqar client."""
kc = self.keystone() kc = self.keystone()
messaging_api_url = kc.service_catalog.url_for( messaging_api_url = kc.service_catalog.url_for(
service_type='messaging', endpoint_type='public', service_type='messaging',
endpoint_type=self.endpoint.endpoint_type,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
conf = {'auth_opts': {'backend': 'keystone', 'options': { conf = {'auth_opts': {'backend': 'keystone', 'options': {
'os_username': self.endpoint.username, 'os_username': self.endpoint.username,
@ -278,7 +286,8 @@ class Clients(object):
"""Return designate client.""" """Return designate client."""
kc = self.keystone() kc = self.keystone()
dns_api_url = kc.service_catalog.url_for( dns_api_url = kc.service_catalog.url_for(
service_type='dns', endpoint_type='public', service_type='dns',
endpoint_type=self.endpoint.endpoint_type,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
client = designate.Client( client = designate.Client(
endpoint=dns_api_url, endpoint=dns_api_url,

View File

@ -18,6 +18,7 @@ import os
import mock import mock
from rally.cmd.commands import deployment from rally.cmd.commands import deployment
from rally import consts
from rally import exceptions from rally import exceptions
from tests import test from tests import test
@ -201,7 +202,7 @@ class DeploymentCommandsTestCase(test.TestCase):
"password": "p", "password": "p",
"tenant_name": "t", "tenant_name": "t",
"region_name": "r", "region_name": "r",
"use_public_urls": "upu", "endpoint_type": consts.EndpointType.INTERNAL,
"admin_port": "ap" "admin_port": "ap"
}, },
"users": [] "users": []
@ -211,8 +212,9 @@ class DeploymentCommandsTestCase(test.TestCase):
mock_deployment.assert_called_once_with(deploy_id) mock_deployment.assert_called_once_with(deploy_id)
headers = ["auth_url", "username", "password", "tenant_name", headers = ["auth_url", "username", "password", "tenant_name",
"region_name", "use_public_urls", "admin_port"] "region_name", "endpoint_type", "admin_port"]
fake_data = ["url", "u", "p", "t", "r", "upu", "ap"] fake_data = ["url", "u", "p", "t", "r", consts.EndpointType.INTERNAL,
"ap"]
mock_struct.assert_called_once_with(**dict(zip(headers, fake_data))) mock_struct.assert_called_once_with(**dict(zip(headers, fake_data)))
mock_print_list.assert_called_once_with([mock_struct()], headers) mock_print_list.assert_called_once_with([mock_struct()], headers)

View File

@ -17,6 +17,7 @@
import jsonschema import jsonschema
from rally import consts
from rally import deploy from rally import deploy
from rally.deploy.engines import existing from rally.deploy.engines import existing
from tests import test from tests import test
@ -30,7 +31,7 @@ class TestExistingCloud(test.TestCase):
"type": "ExistingCloud", "type": "ExistingCloud",
"auth_url": "http://example.net:5000/v2.0/", "auth_url": "http://example.net:5000/v2.0/",
"region_name": "RegionOne", "region_name": "RegionOne",
"use_public_urls": False, "endpoint_type": consts.EndpointType.INTERNAL,
"admin_port": 35357, "admin_port": 35357,
"admin": { "admin": {
"username": "admin", "username": "admin",

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from rally import consts
from rally import objects from rally import objects
from tests import test from tests import test
@ -25,7 +26,8 @@ class EndpointTestCase(test.TestCase):
{"auth_url": "url", "username": "user", {"auth_url": "url", "username": "user",
"password": "pwd", "tenant_name": "tenant", "password": "pwd", "tenant_name": "tenant",
"region_name": None, "permission": "admin", "region_name": None, "permission": "admin",
"domain_name": None, "use_public_urls": False, "domain_name": None,
"endpoint_type": consts.EndpointType.INTERNAL,
"project_domain_name": "Default", "project_domain_name": "Default",
"user_domain_name": "Default", "user_domain_name": "Default",
'admin_port': 35357}) 'admin_port': 35357})

View File

@ -37,7 +37,7 @@ FAKE_DEPLOY_CONFIG = {
"user_domain_name": "Default" "user_domain_name": "Default"
}, },
"region_name": "RegionOne", "region_name": "RegionOne",
"use_public_urls": False, "endpoint_type": consts.EndpointType.INTERNAL,
"admin_port": 35357 "admin_port": 35357
} }

View File

@ -85,7 +85,8 @@ class OSClientsTestCase(test.TestCase):
client = self.clients.nova() client = self.clients.nova()
self.assertEqual(client, fake_nova) self.assertEqual(client, fake_nova)
self.service_catalog.url_for.assert_called_once_with( self.service_catalog.url_for.assert_called_once_with(
service_type='compute', endpoint_type='public', service_type='compute',
endpoint_type=consts.EndpointType.INTERNAL,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
mock_nova.Client.assert_called_once_with( mock_nova.Client.assert_called_once_with(
"2", "2",
@ -112,7 +113,7 @@ class OSClientsTestCase(test.TestCase):
"ca_cert": cfg.CONF.https_cacert "ca_cert": cfg.CONF.https_cacert
} }
self.service_catalog.url_for.assert_called_once_with( self.service_catalog.url_for.assert_called_once_with(
service_type='network', endpoint_type='public', service_type='network', endpoint_type=consts.EndpointType.INTERNAL,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
mock_neutron.Client.assert_called_once_with("2.0", **kw) mock_neutron.Client.assert_called_once_with("2.0", **kw)
self.assertEqual(self.clients.cache["neutron"], fake_neutron) self.assertEqual(self.clients.cache["neutron"], fake_neutron)
@ -129,7 +130,8 @@ class OSClientsTestCase(test.TestCase):
"timeout": cfg.CONF.openstack_client_http_timeout, "timeout": cfg.CONF.openstack_client_http_timeout,
"insecure": False, "cacert": None} "insecure": False, "cacert": None}
self.service_catalog.url_for.assert_called_once_with( self.service_catalog.url_for.assert_called_once_with(
service_type='image', endpoint_type='public', service_type='image',
endpoint_type=consts.EndpointType.INTERNAL,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
mock_glance.Client.assert_called_once_with("1", **kw) mock_glance.Client.assert_called_once_with("1", **kw)
self.assertEqual(self.clients.cache["glance"], fake_glance) self.assertEqual(self.clients.cache["glance"], fake_glance)
@ -143,7 +145,8 @@ class OSClientsTestCase(test.TestCase):
client = self.clients.cinder() client = self.clients.cinder()
self.assertEqual(client, fake_cinder) self.assertEqual(client, fake_cinder)
self.service_catalog.url_for.assert_called_once_with( self.service_catalog.url_for.assert_called_once_with(
service_type='volume', endpoint_type='public', service_type='volume',
endpoint_type=consts.EndpointType.INTERNAL,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
mock_cinder.Client.assert_called_once_with( mock_cinder.Client.assert_called_once_with(
"1", None, None, http_log_debug=False, "1", None, None, http_log_debug=False,
@ -164,7 +167,8 @@ class OSClientsTestCase(test.TestCase):
client = self.clients.ceilometer() client = self.clients.ceilometer()
self.assertEqual(client, fake_ceilometer) self.assertEqual(client, fake_ceilometer)
self.service_catalog.url_for.assert_called_once_with( self.service_catalog.url_for.assert_called_once_with(
service_type='metering', endpoint_type='public', service_type='metering',
endpoint_type=consts.EndpointType.INTERNAL,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
kw = {"endpoint": self.service_catalog.url_for.return_value, kw = {"endpoint": self.service_catalog.url_for.return_value,
"token": self.fake_keystone.auth_token, "token": self.fake_keystone.auth_token,
@ -182,7 +186,8 @@ class OSClientsTestCase(test.TestCase):
client = self.clients.ironic() client = self.clients.ironic()
self.assertEqual(client, fake_ironic) self.assertEqual(client, fake_ironic)
self.service_catalog.url_for.assert_called_once_with( self.service_catalog.url_for.assert_called_once_with(
service_type='baremetal', endpoint_type='public', service_type='baremetal',
endpoint_type=consts.EndpointType.INTERNAL,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
kw = { kw = {
"os_auth_token": self.fake_keystone.auth_token, "os_auth_token": self.fake_keystone.auth_token,
@ -218,7 +223,8 @@ class OSClientsTestCase(test.TestCase):
client = self.clients.zaqar() client = self.clients.zaqar()
self.assertEqual(client, fake_zaqar) self.assertEqual(client, fake_zaqar)
self.service_catalog.url_for.assert_called_once_with( self.service_catalog.url_for.assert_called_once_with(
service_type='messaging', endpoint_type='public', service_type='messaging',
endpoint_type=consts.EndpointType.INTERNAL,
region_name=self.endpoint.region_name) region_name=self.endpoint.region_name)
fake_zaqar_url = self.service_catalog.url_for.return_value fake_zaqar_url = self.service_catalog.url_for.return_value
conf = {'auth_opts': {'backend': 'keystone', 'options': { conf = {'auth_opts': {'backend': 'keystone', 'options': {