Honor service-type aliases in config

The correct config names are based on the official service type, such as
block_storage_api_version or OS_BLOCK_STORAGE_API_VERSION. But, there
are folks who have been using volume_api_version or
OS_VOLUME_API_VERSION.

Support looking for config values based on service-type aliases. The
official type will win.

Change-Id: I13c77ad4fce14a491b6a82f4c7e332d284d14e0d
This commit is contained in:
Monty Taylor
2018-05-08 10:34:35 -05:00
parent 9c774d2959
commit dade89b51f
17 changed files with 88 additions and 27 deletions

View File

@@ -18,6 +18,7 @@ import warnings
from keystoneauth1 import adapter from keystoneauth1 import adapter
import keystoneauth1.exceptions.catalog import keystoneauth1.exceptions.catalog
from keystoneauth1 import session as ks_session from keystoneauth1 import session as ks_session
import os_service_types
import requestsexceptions import requestsexceptions
from six.moves import urllib from six.moves import urllib
@@ -103,6 +104,8 @@ class CloudRegion(object):
self._cache_arguments = cache_arguments self._cache_arguments = cache_arguments
self._password_callback = password_callback self._password_callback = password_callback
self._service_type_manager = os_service_types.ServiceTypes()
def __getattr__(self, key): def __getattr__(self, key):
"""Return arbitrary attributes.""" """Return arbitrary attributes."""
@@ -188,33 +191,62 @@ class CloudRegion(object):
def get_auth_args(self): def get_auth_args(self):
return self.config.get('auth', {}) return self.config.get('auth', {})
def _get_config(
self, key, service_type,
default=None,
fallback_to_unprefixed=False):
'''Get a config value for a service_type.
Finds the config value for a key, looking first for it prefixed by
the given service_type, then by any known aliases of that service_type.
Finally, if fallback_to_unprefixed is True, a value will be looked
for without a prefix to support the config values where a global
default makes sense.
For instance, ``_get_config('example', 'block-storage', True)`` would
first look for ``block_storage_example``, then ``volumev3_example``,
``volumev2_example`` and ``volume_example``. If no value was found, it
would look for ``example``.
If none of that works, it returns the value in ``default``.
'''
for st in self._service_type_manager.get_all_types(service_type):
value = self.config.get(_make_key(key, st))
if value is not None:
return value
if fallback_to_unprefixed:
return self.config.get(key)
return default
def get_interface(self, service_type=None): def get_interface(self, service_type=None):
key = _make_key('interface', service_type) return self._get_config(
interface = self.config.get('interface') 'interface', service_type, fallback_to_unprefixed=True)
return self.config.get(key, interface)
def get_api_version(self, service_type): def get_api_version(self, service_type):
key = _make_key('api_version', service_type) return self._get_config('api_version', service_type)
return self.config.get(key, None)
def get_service_type(self, service_type): def get_service_type(self, service_type):
# People requesting 'volume' are doing so because os-client-config # People requesting 'volume' are doing so because os-client-config
# let them. What they want is block-storage, not explicitly the # let them. What they want is block-storage, not explicitly the
# v1 of cinder. If someone actually wants v1, they'll have api_version # v1 of cinder. If someone actually wants v1, they'll have api_version
# set to 1, in which case block-storage will still work properly. # set to 1, in which case block-storage will still work properly.
if service_type == 'volume': # Use service-types-manager to grab the official type name. _get_config
service_type = 'block-storage' # will still look for config by alias, but starting with the official
key = _make_key('service_type', service_type) # type will get us things in the right order.
return self.config.get(key, service_type) if self._service_type_manager.is_known(service_type):
service_type = self._service_type_manager.get_service_type(
service_type)
return self._get_config(
'service_type', service_type, default=service_type)
def get_service_name(self, service_type): def get_service_name(self, service_type):
key = _make_key('service_name', service_type) return self._get_config('service_name', service_type)
return self.config.get(key, None)
def get_endpoint(self, service_type): def get_endpoint(self, service_type):
key = _make_key('endpoint_override', service_type) value = self._get_config('endpoint_override', service_type)
old_key = _make_key('endpoint', service_type) if not value:
return self.config.get(key, self.config.get(old_key, None)) value = self._get_config('endpoint', service_type)
return value
@property @property
def prefer_ipv6(self): def prefer_ipv6(self):

View File

@@ -2,6 +2,7 @@
"application_catalog_api_version": "1", "application_catalog_api_version": "1",
"auth_type": "password", "auth_type": "password",
"baremetal_api_version": "1", "baremetal_api_version": "1",
"block_storage_api_version": "2",
"container_api_version": "1", "container_api_version": "1",
"container_infra_api_version": "1", "container_infra_api_version": "1",
"compute_api_version": "2", "compute_api_version": "2",

View File

@@ -51,6 +51,12 @@
"default": "1", "default": "1",
"type": "string" "type": "string"
}, },
"block_storage_api_version": {
"name": "Block Storage API Version",
"description": "Block Storage API Version",
"default": "2",
"type": "string"
},
"compute_api_version": { "compute_api_version": {
"name": "Compute API Version", "name": "Compute API Version",
"description": "Compute API Version", "description": "Compute API Version",
@@ -103,6 +109,7 @@
"required": [ "required": [
"auth_type", "auth_type",
"baremetal_api_version", "baremetal_api_version",
"block_storage_api_version",
"compute_api_version", "compute_api_version",
"database_api_version", "database_api_version",
"disable_vendor_agent", "disable_vendor_agent",
@@ -115,7 +122,6 @@
"interface", "interface",
"network_api_version", "network_api_version",
"object_store_api_version", "object_store_api_version",
"secgroup_source", "secgroup_source"
"volume_api_version"
] ]
} }

View File

@@ -168,6 +168,11 @@
"description": "Baremetal API Service Type", "description": "Baremetal API Service Type",
"type": "string" "type": "string"
}, },
"block_storage_api_version": {
"name": "Block Storage API Version",
"description": "Block Storage API Version",
"type": "string"
},
"compute_api_version": { "compute_api_version": {
"name": "Compute API Version", "name": "Compute API Version",
"description": "Compute API Version", "description": "Compute API Version",

View File

@@ -9,6 +9,6 @@
], ],
"identity_api_version": "3", "identity_api_version": "3",
"image_format": "raw", "image_format": "raw",
"volume_api_version": "3" "block_storage_api_version": "3"
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"name": "bluebox", "name": "bluebox",
"profile": { "profile": {
"volume_api_version": "1", "block_storage_api_version": "1",
"region_name": "RegionOne" "region_name": "RegionOne"
} }
} }

View File

@@ -9,7 +9,7 @@
"nz_wlg_2" "nz_wlg_2"
], ],
"image_api_version": "1", "image_api_version": "1",
"volume_api_version": "1", "block_storage_api_version": "1",
"image_format": "raw" "image_format": "raw"
} }
} }

View File

@@ -13,7 +13,7 @@
"Kna1" "Kna1"
], ],
"requires_floating_ip": true, "requires_floating_ip": true,
"volume_api_version": "1", "block_storage_api_version": "1",
"identity_api_version": "3" "identity_api_version": "3"
} }
} }

View File

@@ -6,7 +6,7 @@
}, },
"identity_api_version": "3", "identity_api_version": "3",
"image_api_version": "1", "image_api_version": "1",
"volume_api_version": "1", "block_storage_api_version": "1",
"regions": [ "regions": [
"it-mil1", "it-mil1",
"nl-ams1", "nl-ams1",

View File

@@ -10,6 +10,6 @@
"cystack" "cystack"
], ],
"identity_api_version": "3", "identity_api_version": "3",
"volume_api_version": "3" "block_storage_api_version": "3"
} }
} }

View File

@@ -4,7 +4,7 @@
"auth": { "auth": {
"auth_url": "https://identity.open.softlayer.com" "auth_url": "https://identity.open.softlayer.com"
}, },
"volume_api_version": "2", "block_storage_api_version": "2",
"identity_api_version": "3", "identity_api_version": "3",
"regions": [ "regions": [
"london" "london"

View File

@@ -19,7 +19,7 @@
"floating_ip_source": "None", "floating_ip_source": "None",
"secgroup_source": "None", "secgroup_source": "None",
"requires_floating_ip": false, "requires_floating_ip": false,
"volume_api_version": "1", "block_storage_api_version": "1",
"disable_vendor_agent": { "disable_vendor_agent": {
"vm_mode": "hvm", "vm_mode": "hvm",
"xenapi_use_agent": false "xenapi_use_agent": false

View File

@@ -8,7 +8,7 @@
"LS", "LS",
"ZH" "ZH"
], ],
"volume_api_version": "1", "block_storage_api_version": "1",
"image_api_use_tasks": true, "image_api_use_tasks": true,
"image_format": "raw" "image_format": "raw"
} }

View File

@@ -5,7 +5,7 @@
"auth_url": "https://console.ultimum-cloud.com:5000/" "auth_url": "https://console.ultimum-cloud.com:5000/"
}, },
"identity_api_version": "3", "identity_api_version": "3",
"volume_api_version": "1", "block_storage_api_version": "1",
"region-name": "RegionOne" "region-name": "RegionOne"
} }
} }

View File

@@ -8,7 +8,7 @@
"bj1", "bj1",
"gd1" "gd1"
], ],
"volume_api_version": "1", "block_storage_api_version": "1",
"identity_api_version": "3", "identity_api_version": "3",
"image_format": "raw", "image_format": "raw",
"floating_ip_source": "None" "floating_ip_source": "None"

View File

@@ -150,6 +150,16 @@ class TestCloudRegion(base.TestCase):
self.assertIsNone(cc.get_service_name('compute')) self.assertIsNone(cc.get_service_name('compute'))
self.assertEqual('locks', cc.get_service_name('identity')) self.assertEqual('locks', cc.get_service_name('identity'))
def test_aliases(self):
services_dict = fake_services_dict.copy()
services_dict['volume_api_version'] = 12
services_dict['alarming_service_name'] = 'aodh'
cc = cloud_region.CloudRegion("test1", "region-al", services_dict)
self.assertEqual('12', cc.get_api_version('volume'))
self.assertEqual('12', cc.get_api_version('block-storage'))
self.assertEqual('aodh', cc.get_service_name('alarm'))
self.assertEqual('aodh', cc.get_service_name('alarming'))
def test_no_override(self): def test_no_override(self):
"""Test no override happens when defaults are not configured""" """Test no override happens when defaults are not configured"""
cc = cloud_region.CloudRegion("test1", "region-al", fake_services_dict) cc = cloud_region.CloudRegion("test1", "region-al", fake_services_dict)

View File

@@ -0,0 +1,7 @@
---
features:
- |
Config values now support service-type aliases. The correct config names
are based on the official service type, such as
``block_storage_api_version``, but with this change, legacy aliases such
as ``volume_api_version`` are also supported.